<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7557194597309413467</id><updated>2012-01-27T12:04:01.540-05:00</updated><category term='git repository'/><category term='ruby oci8 os_x mac snow_leopard'/><category term='goat-time'/><category term='shib shibboleth shibbolize uportal login auth authn authorization'/><category term='macruby ruby os_x mac hotcocoa'/><category term='schema sleuth ssleuth find related data automatically oracle dbi unix osx'/><category term='oracle rails session sequence unique constraint violation'/><category term='15 second seconds ruby rails migrate migration db database model easy'/><category term='rails ruby database schema dump diff compare text file tool utility oracle'/><category term='ruby rails migration ORA-04043 oracle error'/><category term='cms vcs'/><category term='cap capistrano capshell command-line multiple'/><category term='blog stats'/><category term='ruby error before_filter'/><category term='git prompt'/><category term='ruby Net::HTTP use_ssl'/><category term='ruby gem version ssh remote'/><category term='rails ruby model activerecord html store multiple comma-delimited select dropdown single'/><category term='https virtual_host shibboleth test testing'/><category term='spring root portlet servlet context beans'/><category term='tomcat hotdeploy webapp portlet memory leak visualvm jconsole jmap jhat mat hproc'/><category term='shib shibboleth shibbolize uportal jmeter test login auth authn authorization'/><category term='java analysis profiling thread dump jstack jda jconsole visualvm'/><category term='ojdbc driver debug logging log java database'/><category term='rails activerecord id ORA-02289 oracle'/><category term='java base64 peoplecode peoplesoft apache commons codec'/><category term='java osx'/><category term='os_x macruby hotcocoa github'/><category term='ruby rails activesupport from_xml xml parse string duplicate keys'/><category term='os_x git gitx'/><category term='osx linux unix console file directory size human readable du sort df cli bash'/><category term='console command bash linux osx unix'/><category term='java bug'/><category term='ruby rails bundler gem git'/><category term='git branch'/><category term='cross-comain portlet iframe'/><category term='facebook stream javascript portlet'/><title type='text'>Sthyo</title><subtitle type='html'>Java, Ruby/Rails, etc.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default?start-index=101&amp;max-results=100'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>329</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5810731887258160984</id><published>2012-01-04T12:34:00.004-05:00</published><updated>2012-01-04T12:38:56.926-05:00</updated><title type='text'>Workaround for "certificate verify failed" and "undefined method 'read_nonblock'"</title><content type='html'>If you are getting the error "NoMethodError: undefined method `read_nonblock' for #&amp;lt;OpenSSL::SSL::SSLSocket:...&amp;gt;" or "OpenSSL::SSL::SSLError: certificate verify failed" using JRuby 1.6.5/Ruby 1.9, update JRuby to 1.6.6 or later for the former error, or check out the following.&lt;br /&gt;
&lt;p/&gt;Thanks to Jeremy for finding the related monkey patch BufferedIO monkeypatch that works in JRuby 1.6.5/Ruby 1.9:&lt;br /&gt;
&lt;p/&gt;&lt;pre&gt;&lt;code&gt;
require 'net/http'
require 'net/https'
require 'uri'
require 'openssl'

# Avoid error: NoMethodError: undefined method `read_nonblock' for #&amp;lt;OpenSSL::SSL::SSLSocket:...&amp;gt;
# See: http://jira.codehaus.org/browse/JRUBY-5529
Net::BufferedIO.class_eval do
    BUFSIZE = 1024 * 16
 
    def rbuf_fill
      timeout(@read_timeout) {
        @rbuf &amp;lt;&amp;lt; @io.sysread(BUFSIZE)
      }
    end
end

uri = URI.parse('https://host.with.bad.cert/some/path?a=1')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
# Avoid error, if unavoidable: &amp;quot;OpenSSL::SSL::SSLError: certificate verify failed&amp;quot;
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
puts response.body
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;&lt;em&gt;Note: The "read_nonblock" error is fixed in JRuby 1.6.6.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5810731887258160984?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5810731887258160984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5810731887258160984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5810731887258160984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5810731887258160984'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2012/01/workaround-for-certificate-verify.html' title='Workaround for &quot;certificate verify failed&quot; and &quot;undefined method &apos;read_nonblock&apos;&quot;'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4546932971396587724</id><published>2011-11-16T14:44:00.001-05:00</published><updated>2011-11-16T15:12:53.227-05:00</updated><title type='text'>All Mobile user-agent Strings in a Text File</title><content type='html'>&lt;a href="http://sourceforge.net/projects/wurfl/"&gt;WURFL&lt;/a&gt; is a great project dedicated to collecting data on wireless/mobile devices. If you just want a list of the user-agent strings, though, it is quite a bit of XML to sift through. You could parse it, or just convert it to a text file list of mobile user-agents. If you are doing the latter, you could use this script I wrote:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
#!/bin/bash

if [ $# -eq 0 ]
then
  echo "Download and extract the latest wurfl.xml from http://sourceforge.net/projects/wurfl/files/WURFL/"
  echo "then use this script to extract the wireless user agent strings."
  echo ""
  echo "usage: wurfltxt wurfl.xml"
  exit 1
fi

if [ ! -f "$1" ]
then
  echo "the first argument must be a valid path to wurfl.xml"
  exit 1
fi

grep user_agent $1 &amp;gt; wurfl.txt
sed 's/.*user_agent="//g' wurfl.txt &amp;gt; wurfl2.txt
sed 's/"\ fall_back.*//g' wurfl2.txt &amp;gt; wurfl.txt
rm wurfl2.txt
sort wurfl.txt &amp;gt; wurfl_sorted.txt
rm wurfl.txt
mv wurfl_sorted.txt wurfl.txt
echo Created wurfl.txt
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Save that to a file called wurfltxt and then:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
chmod +x wurfltxt
wurfltxt /path/to/wurfl.xml
&lt;/code&gt;&lt;/pre&gt;and it will generate a wurfl.txt file containing just the complete WURFL list of mobile device user-agents.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4546932971396587724?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4546932971396587724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4546932971396587724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4546932971396587724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4546932971396587724'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/11/all-mobile-user-agent-strings-in-text.html' title='All Mobile user-agent Strings in a Text File'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5443287219022921028</id><published>2011-10-14T10:45:00.001-04:00</published><updated>2011-10-14T10:45:14.930-04:00</updated><title type='text'>Tomcat 6 - SEVERE: Error listenerStart - How to Log the Stacktrace</title><content type='html'>If you run into the Tomcat 6 error "SEVERE: Error listenerStart", a quick way to get logging to work so you can see the error/exception/stacktrace is to add the following file to a file logging.properties that you should put into webapps/your_webapp_name/WEB-INF/classes (putting it into conf/logging.properties didn't work):&lt;br /&gt;
&lt;p/&gt;&lt;pre&gt;&lt;code&gt;
org.apache.catalina.core.ContainerBase.[Catalina].level = FINEST
org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;Thanks to Venkatt Guhesan's &lt;a href="http://java.dzone.com/articles/tomcat-6-infamous-%E2%80%9Csevere"&gt;post&lt;/a&gt; for this info.&lt;br /&gt;
&lt;p/&gt;In our case, the only file in work/Catalina/localhost/your_webapp_name/ was SESSIONS.ser. This seemed to indicate that maybe it was unable to compile something or to load the classes. It turned out to be a missing class/jar.&lt;br /&gt;
&lt;p/&gt;The resulting stacktrace in my case was similar to:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
 at org.springframework.web.context.ContextLoader.&lt;init&gt;(ContextLoader.java:139)
 at org.springframework.web.context.ContextLoaderListener.createContextLoader(ContextLoaderListener.java:57)
 at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:48)
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3972)
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4467)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:526)
 at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:905)
 at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:740)
 at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:500)
 at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
 at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
 at org.apache.catalina.core.StandardService.start(StandardService.java:516)
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:593)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1484)
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1329)
 ... 27 more
Oct 14, 2011 10:11:30 AM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Oct 14, 2011 10:11:30 AM org.apache.catalina.core.StandardContext start
SEVERE: Context [/your_webapp_name] startup failed due to previous errors
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;Of course, your error is probably different.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5443287219022921028?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5443287219022921028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5443287219022921028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5443287219022921028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5443287219022921028'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/10/tomcat-6-severe-error-listenerstart-how.html' title='Tomcat 6 - SEVERE: Error listenerStart - How to Log the Stacktrace'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7018127349464901818</id><published>2011-09-29T16:03:00.002-04:00</published><updated>2011-10-07T16:39:46.589-04:00</updated><title type='text'>Migrating Rails from MySQL to Oracle</title><content type='html'>Assuming you have MySQL, Oracle, and Oracle Client (with sqlplus) setup and have already created the schema, then you just do the following: (We created the schema via Rails, first with rake db:schema:dump then rake db:schema:load after adding names to indexes and shortening column names and reference to those attributes. The benefit of doing it that way was to ensure the correct datatypes for Active Record would be created.)&lt;br /&gt;
&lt;p/&gt;&lt;pre&gt;&lt;code&gt;
mysqldump -u your_username --password='your_password'  name_of_mysql_database --compatible=oracle --no-create-info --no-create-db --skip-opt --skip-set-charset --skip-extended-insert --skip-comments --skip-quote-names --compact &amp;gt; /some/path/backup.sql
cd /some/path/
grep ដ backup.sql
# Look at the output of grep. If it returns anything, change the unicode character here and later.
# Changes 2 sequential backslashes to a unicode character temporarily.
sed -e "s/\\\\\\\\/ដ/g" backup.sql &gt; backup.sql.1
# Unescape characters that mysqldump escapes.
# Note: there is a good chance that the escape character replacements will fail to work when executed. Because we had a table with heavy use of escape characters that
# made sqlplus choke. You might want to look at the generated SQL and adjust these accordingly. Possibly characters escaped at beginning or end of value or next to each other won't work without more replacements to make those valid, since double single-quote is an escaped single-quote in SQL.
sed -e "s/\\\\'/''/g" \
    -e "s/\\\\0/'||Chr(0)||'/g" \
    -e "s/\\\\a/'||Chr(7)||'/g" \
    -e "s/\\\\b/'||Chr(8)||'/g" \
    -e "s/\\\\t/'||Chr(9)||'/g" \
    -e "s/\\\\n/'||Chr(10)||'/g" \
    -e "s/\\\\f/'||Chr(12)||'/g" \
    -e "s/\\\\r/'||Chr(13)||'/g" \
    -e "s/\\\\e/'||Chr(27)||'/g" \
    -e "s/\\\\"/"/g" \
    backup.sql.1 &gt; backup.sql.2
# The first expression changes the unicode char back to 2 sequential backslashes. The second two expressions fix dates. You may need to alter the date format.
sed -e "s/ដ/\\\\/g" \
    -e "s/'[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'/to_date(&amp;amp;,'yyyy-mm-dd HH24:MI:SS')/g" \
    -e "s/'[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'/to_date(&amp;amp;,'yyyy-mm-dd')/g" \
    backup.sql.2 &gt; backup.sql.3
sqlplus oracle_username/oracle_password@host:port/SID
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;The following is done in sqlplus:&lt;br /&gt;
&lt;p/&gt;&lt;pre&gt;&lt;code&gt;
-- this makes ampersands ok
SET SCAN OFF
-- this commits after every insert
SET AUTOCOMMIT ON
-- this outputs the insert, so that when there is an error, you know what it was trying to execute
SET ECHO ON
-- this eliminates output stating how many rows were created
SET FEEDBACK OFF
-- this shows the current time next to each statement execution, so in the end you know how long it took and when there were errors
SET TIME ON
@/some/path/backup.sql.3
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Basically, this does the export, does text alterations to unescape and Oracle SQL-fy, and makes the datetimes and dates into Oracle datetimes and dates. Then it imports it. This may not work for you, or might require adjustments to work properly.&lt;br /&gt;
&lt;p/&gt;Note: we first tried Oracle SQLDeveloper to migrate the data. It required dba access for the schema user, created two users, granted one of them various rights, and failed in the end. Maybe it would work for you, though.&lt;br /&gt;
&lt;p/&gt;When you're done, to test out that the data is the same between the MySQL and Oracle you could try using my &lt;a href="https://github.com/garysweaver/schema-dump"&gt;schema-dump&lt;/a&gt; utility to output the data in both databases and diff the two files.&lt;br /&gt;
&lt;p/&gt;&lt;a href="http://kettle.pentaho.org/"&gt;Pentaho&lt;/a&gt; was mentioned as a possibility for a migration tool in a Stack Overflow thread about &lt;a href="http://stackoverflow.com/questions/5417386/import-mysql-dump-to-postgresql-database"&gt;MySQL to PostgreSQL migration&lt;/a&gt;, so you might look into that also.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7018127349464901818?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7018127349464901818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7018127349464901818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7018127349464901818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7018127349464901818'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/09/how-to-migrate-mysql-databases-data.html' title='Migrating Rails from MySQL to Oracle'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5706976431482526076</id><published>2011-09-14T13:03:00.000-04:00</published><updated>2011-09-14T13:21:04.325-04:00</updated><title type='text'>Bash Script to Automate Import of External Cert Given Host and Port Into Java Keystore</title><content type='html'>Here's a bash script to import an external cert and import it into the local JDK's keystore, using some commands I found here:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://serverfault.com/questions/129503/save-remote-ssl-certificate-via-linux-command-line"&gt;http://serverfault.com/questions/129503/save-remote-ssl-certificate-via-linux-command-line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html"&gt;http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.codehaus.org/display/JETTY/How+to+configure+SSL"&gt;http://docs.codehaus.org/display/JETTY/How+to+configure+SSL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;Save this to a file called add_cert, then chmod +x add_cert and put it in your path:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
#!/bin/bash

# add_cert
# Written by Gary S. Weaver 2011-09-14
# Downloads cert and imports it automatically into Java keystore.
# This is useful to run immediately after updating the JDK with a new keystore.

# References:
# http://serverfault.com/questions/129503/save-remote-ssl-certificate-via-linux-command-line
# http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html
# http://docs.codehaus.org/display/JETTY/How+to+configure+SSL

set -e

KEYTOOL_PATHNAME=$1
KEYSTORE_PATHNAME=$2
KEYSTORE_PASSPHRASE=$3
HOST=$4
PORT=$5

if [ $# -eq 0 ]
then
  echo &amp;quot;&amp;quot;
  echo &amp;quot;usage: add_cert keytool_pathname keystore_pathname passphrase host [optional_port]&amp;quot;
  exit 1
fi

if [ ! -f &amp;quot;$KEYTOOL_PATHNAME&amp;quot; ]
then
  echo &amp;quot;the first argument must be a valid path to the keytool executable (e.g. '\$JAVA_HOME/bin/keytool'): '$KEYTOOL_PATHNAME'&amp;quot;
  echo &amp;quot;&amp;quot;
  echo &amp;quot;usage: add_cert keytool_pathname keystore_pathname passphrase host [optional_port]&amp;quot;
  exit 1
fi

if [ ! -f &amp;quot;$KEYSTORE_PATHNAME&amp;quot; ]
then
  echo &amp;quot;the second argument must be a valid path to the keystore (e.g. '\$JAVA_HOME/jre/lib/security/jssecacerts'): '$KEYSTORE_PATHNAME'&amp;quot;
  echo &amp;quot;&amp;quot;
  echo &amp;quot;usage: add_cert keytool_pathname keystore_pathname passphrase host [optional_port]&amp;quot;
  exit 1
fi

if [ -z &amp;quot;$KEYSTORE_PASSPHRASE&amp;quot; ]
then
  echo &amp;quot;the third argument must be a valid passphrase (e.g. 'changeit'): '$KEYSTORE_PASSPHRASE'&amp;quot;
  echo &amp;quot;&amp;quot;
  echo &amp;quot;usage: add_cert keytool_pathname keystore_pathname passphrase host [optional_port]&amp;quot;
  exit 1
fi

if [ -z &amp;quot;$HOST&amp;quot; ]
then
  echo &amp;quot;the fourth argument must be a valid hostname (e.g. www.acme.org): '$HOST'&amp;quot;
  echo &amp;quot;&amp;quot;
  echo &amp;quot;usage: add_cert keytool_pathname keystore_pathname passphrase host [optional_port]&amp;quot;
  exit 1
fi

if [ -z &amp;quot;$PORT&amp;quot; ]
then
  PORT=443
fi

echo &amp;quot;openssl s_client -connect $HOST:$PORT /tmp/$HOST.pem&amp;quot;
openssl s_client -connect $HOST:$PORT /tmp/$HOST.pem
echo &amp;quot;$KEYTOOL_PATHNAME -keystore jssecacerts -import -alias $HOST -file /tmp/$HOST.pem -trustcacerts -noprompt -storepass $KEYSTORE_PASSPHRASE&amp;quot;
$KEYTOOL_PATHNAME -keystore $KEYSTORE_PATHNAME -import -alias $HOST -file /tmp/$HOST.pem -trustcacerts -noprompt -storepass $KEYSTORE_PASSPHRASE
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
In addition, here are some helpful commands:&lt;br /&gt;
&lt;br /&gt;
List all certs by alias in alphanumeric order:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
$JAVA_HOME/bin/keytool -list -v -keystore $JAVA_HOME/jre/lib/security/keystore_name -storepass store_password | grep "Alias name" | sort
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Remove a cert given its alias:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
$JAVA_HOME/bin/keytool -delete -alias alias_name -keystore $JAVA_HOME/jre/lib/security/keystore_name -storepass store_password
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5706976431482526076?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5706976431482526076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5706976431482526076' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5706976431482526076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5706976431482526076'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/09/bash-script-to-automate-import-of.html' title='Bash Script to Automate Import of External Cert Given Host and Port Into Java Keystore'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2970064788095321835</id><published>2011-08-26T12:02:00.004-04:00</published><updated>2011-08-26T12:15:10.744-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oracle rails session sequence unique constraint violation'/><title type='text'>OCIError: ORA-00001: unique constraint (APP.SYS_C9876543210) violated: INSERT INTO sessions</title><content type='html'>Maintaining an older app that uses Rails session persistence in the database SESSIONS table, and after a restore, we got the following issue:
&lt;p/&gt;
OCIError: ORA-00001: unique constraint (APP.SYS_C9876543210) violated: INSERT INTO sessions (data, created_at, updated_at, session_id, id) VALUES(empty_clob(), TO_DATE('2011-08-26 10:55:08','YYYY-MM-DD HH24:MI:SS'), TO_DATE('2011-08-26 10:55:08','YYYY-MM-DD HH24:MI:SS'), 'd33f1cb3386333e7fa7a4c8b206a0716a08e396f07b28171bd9ed13a14bc8', 3478952)
...
&lt;p/&gt;
The issue is that the session id that it is trying to insert is not unique, so it is violating the primary key constraint on the table. You can fix this manually by clearing out the SESSIONS table, or you can use:
&lt;pre&gt;&lt;code&gt;
$ rake db:sessions:clear
&lt;/code&gt;&lt;/pre&gt;
Why this happened: in the example above, the '3478952' value is from the sequence associated with the SESSIONS table. I had erroneously requested a restore of tables to the database, so the DBA didn't restore the sequences and other objects with the Oracle user. The restored data (copied from a different environment) had more data in SESSIONS and a greater sequence number. To ensure there won't be other issues with sequences, etc. I'm asking the DBA to do another restore, this time copying all objects.
&lt;p/&gt;
&lt;em&gt;(I replaced a few values in the error message to make it more generic for this post.)&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2970064788095321835?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2970064788095321835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2970064788095321835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2970064788095321835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2970064788095321835'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/08/ocierror-ora-00001-unique-constraint.html' title='OCIError: ORA-00001: unique constraint (APP.SYS_C9876543210) violated: INSERT INTO sessions'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8485054040625117058</id><published>2011-08-26T11:42:00.001-04:00</published><updated>2011-08-26T11:43:01.742-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails ruby database schema dump diff compare text file tool utility oracle'/><title type='text'>Dump Database or Schema to a Diffable Text File with Schema Dump</title><content type='html'>Just wrote a new tool called &lt;a href="https://github.com/garysweaver/schema-dump"&gt;Schema Dump&lt;/a&gt; that dumps a database or schema data to a text file that you can then use the sort and diff (compare) commands with to do a diff of changes between two schemas or databases. Pretty simple script using Ruby DBI and trollop.
&lt;p/&gt;
Some examples of schemadump command-line:
&lt;pre&gt;&lt;code&gt;
$ schemadump -r DBI:OCI8://db.acme.org:1234/ACMETEST -u jdoe -p secret

SAMPLE_TABLE_A: '123', 'Joe'
SAMPLE_TABLE_B: '123', '234'
SAMPLE_TABLE_B: '123', '235'
SAMPLE_TABLE_C: '234', 'Kia', 'Sorento', '345'
SAMPLE_TABLE_C: '235', 'Kia', 'Sportage', '346'
SAMPLE_TABLE_D: '345', 'Red'
SAMPLE_TABLE_D: '346', 'Green'
&lt;/pre&gt;&lt;/code&gt;

&lt;pre&gt;&lt;code&gt;
$ schemadump -r DBI:OCI8://db.acme.org:1234/ACMETEST -u jdoe -p secret &gt; test
$ sort test &gt; test-sorted
$ schemadump -r DBI:OCI8://db.acme.org:3456/ACMEPROD -u jdoe -p secret &gt; prod
$ sort prod &gt; prod-sorted
$ diff test-sorted prod-sorted
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8485054040625117058?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8485054040625117058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8485054040625117058' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8485054040625117058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8485054040625117058'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/08/dump-database-or-schema-to-diffable.html' title='Dump Database or Schema to a Diffable Text File with Schema Dump'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5693163906662682411</id><published>2011-05-10T15:23:00.014-04:00</published><updated>2011-05-10T16:31:48.394-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat hotdeploy webapp portlet memory leak visualvm jconsole jmap jhat mat hproc'/><title type='text'>Tomcat and Webapp Hot-deploy Permgen "Leaks"</title><content type='html'>Spent the last few days trying to fix an issue of running out of permgen when hot-deploying (removing old war to undeploy and adding new war to deploy while Tomcat is running).
&lt;p/&gt;
Using (old) Tomcat 5.5.20, I attached via JMX remotely from JConsole and watched the permgen climb during deploy, climb a tiny bit during undeploy, then climb more during deploy, etc. as I repeated until running out of permgen for a portlet war (webapp).
&lt;p/&gt;
I tweaked the settings until I had this in catalina.sh (this is insecurely opening up JMX btw):
&lt;pre&gt;&lt;code&gt;
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=name.of.the.host \
                      -XX:+UseParNewGC \
                      -XX:+UseConcMarkSweepGC \
                      -XX:+CMSPermGenSweepingEnabled \
                      -XX:+CMSClassUnloadingEnabled \
                      -Dcom.sun.management.jmxremote \
                      -Dcom.sun.management.jmxremote.ssl=false \
                      -Dcom.sun.management.jmxremote.port=(specify open port here) \
                      -Dcom.sun.management.jmxremote.authenticate=false \
                      -Djava.library.path=/usr/lib:/usr/lib64 \
                      -Xmx1024m \
                      -Xms1024m \
                      -XX:MaxPermSize=128m \
                      -XX:NewSize=128m \
                      -XX:MaxTenuringThreshold=0 \
                      -XX:+UseTLAB \
                      -XX:SurvivorRatio=128 \
                      "
&lt;/code&gt;&lt;/pre&gt;
(notice: I would have set permgen size to 256m here, but was trying to test it failing due to lack of permgen during hot-deploys.)
&lt;p/&gt;
I then switched to Tomcat 7.0.12 and did same and also tried out VisualVM. I could see that the permgen even with the same settings started off much lower. The deploys made permgen jump even more than before, though- at least that is how it appeared; I didn't do quantitative measurement even though I probably should have; I was just "spiking" it. The undeploys between the deploys didn't make permgen go up really so that was nice. Long story short: it still ran out of permgen for the portlet (webapp) that I was redeploying.
&lt;p/&gt;
I tried against and used Tomcat 7's new /manager/text/findleaks. All this did was just print out that the portlet/webapp I was hot-deploying was causing a memory leak. This would have been more useful if I hadn't already been focusing on a particular webapp I knew had an issue. It would really be nice to have something that could tell you not only what webapps were a problem, but could help you diagnose what classes/instances are sticking around after you undeploy that maybe shouldn't be there. I also think that logging leaks may be more helpful than using part of manager, because many don't deploy manager (they remove it).
&lt;p/&gt;
I then used jmap to create hprofs (dumps) that I first looked at in VisualVM to compare side-by-side. On the server, I did:
&lt;pre&gt;&lt;code&gt;
ps auxf|grep java
&lt;/code&gt;&lt;/pre&gt;
I got the process id and then did the following, first after the first hot-deploy, second after undeploying, and third after redeploying again (just moving around the same war in and out of webapps directory):
&lt;pre&gt;&lt;code&gt;
jmap /tmp/(some_filename).hprof (process id)
&lt;/code&gt;&lt;/pre&gt;
(note: be sure to tar.gz these via tar -czvf filename.hprof before scp'ing them if it helps to save time.)
&lt;p/&gt;
I tried &lt;a href="http://www.eclipse.org/mat/downloads.php"&gt;Mat&lt;/a&gt; (Eclipse Memory Analyzer, which is a standalone tool so don't have to have/use Eclipse) to look at the pie charts and dominator trees. I found that after opening/loading the heaps to view side-by-side, when I clicked on Histogram icon (looks like a bar graph) that it would show an icon to the right called "Compare to Another Heap Dump", so I tried that. When I compared the first deploy to the heap after the second deploy, things that stood out (in addition to normal types and collections) were instances resulting from reflection (Method objects), JarFile and URLJarFile instances, and xerces's XSSimpleTypeDecl. However, focusing on the new instances wasn't helpful. I was actually interested in what wasn't new. It would be nice if there were a way to focus on what instances where the same between the two dumps. Is there an easy way of doing that with VisualVM? I didn't see one. And that would require me to eliminate much of the stuff that &lt;em&gt;should&lt;/em&gt; stay the same from the results (Tomcat jars, etc.). It just isn't that easy yet.
&lt;p/&gt;
I also used JHat to browse and crawl the difference:
&lt;pre&gt;&lt;code&gt;
jhat -J-Xmx2048m -baseline ~/Desktop/after_1st_hotdeploy.hprof ~/Desktop/after_2nd_hotdeploy.hprof
&lt;/code&gt;&lt;/pre&gt;
(note: ironically it first ran out of memory when I tried to compare without using -J to give it more memory.)
&lt;p/&gt;
It was a little harder to make use of browsing the results via served html and showing both new and old instances in the diff. It is also fairly slow and drags the system down a bit. Here at first I was again probably wrongly focused on the new instances rather than the ones that remained between deploys.
&lt;p/&gt;
Going back and looking at both Mat and JHat later, I'm thinking that I should have removed all but the absolute necessities for the webapp, because all of the classes loaded by Tomcat for every other webapp, common dependencies, etc. get in the way of trying to diagnose what shouldn't have been left behind. And, maybe I should have only focused on what remained after the undeploy.
&lt;p/&gt;
I read this post/interview about Tomcat 7's memory leak protection and about the various things in webapps that can cause leaks:&lt;br/&gt;
&lt;a href="http://java.dzone.com/articles/memory-leak-protection-tomcat"&gt;http://java.dzone.com/articles/memory-leak-protection-tomcat&lt;/a&gt;
&lt;p/&gt;
It was an older interview and not totally surprising, but it is nice to know that at least someone was working on trying to clean up other people's messes when it comes to memory leaks related to hot-deploys and undeploys.
&lt;p/&gt;
All that said, here are some recommendations for diagnosing permgen memory leaks related to undeploys/hot-deploys:
&lt;ol&gt;
&lt;li&gt;Determine which webapps have leaks by either using JConsole or VisualVM to watch permgen as you undeploy and redeploy, or by undeploying and redeploying each webapp and then using Tomcat 7's findleaks to tell you which webapps are leaking.&lt;/li&gt;
&lt;li&gt;After determining which webapps to focus on, create a new Tomcat environment like the old one but where you really limit jars and webapps to only those absolutely necessary to test the hot-deploy leak issue.&lt;/li&gt;
&lt;li&gt;Finally, do diffs with JHat and determine what is the same (not marked as new) and try to exclude in your mind those packages loaded by Tomcat to focus on the others, or you may use Mat and visually compare dominator trees, etc.&lt;/li&gt;
&lt;/ol&gt;
Unfortunately, the last item is the tough one. You might be better off researching possible leaks in versions of jars/libraries you are using and then carefully updating Tomcat and jars used by your webapps to the latest versions- hoping that the leaks have been fixed. Also, do what you can to ensure that threads, connections, and anything else your webapp starts/uses/references (directly or indirectly) is cleaned up as much as possible.
&lt;p/&gt;
&lt;em&gt;Edit: Christopher Schultz on the Tomcat users mailing list said:&lt;/em&gt;&lt;br/&gt;
&lt;blockquote&gt;
Generally speaking, when you have a permgen "leak" across webapp
redeployments, this is the situation:
&lt;p/&gt;
1. Webapp invokes some code that stores a reference to the webapp's
  WebappClassLoader
&lt;p/&gt;
2. That reference is not cleared during undeploy [this is the leak]
&lt;p/&gt;
The big problem is that the WebappClassLoader keeps a reference to all
java.lang.Class objects it loads, so it can be quite bulky when it
leaks, depending on exactly how many classes your webapp has locally.
&lt;p/&gt;
markt has a great presentation which lays out the anatomy of these types
of memory leaks, how to diagnose them, and often how to fix them. These
are slides from a presentation at last year's ApacheCon NA. It's /very/
readable.
&lt;p/&gt;
&lt;a href="http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf"&gt;http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf&lt;/a&gt;
&lt;p/&gt;
- -chris
&lt;/blockquote&gt;
&lt;em&gt;That is a very helpful presentation!&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5693163906662682411?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5693163906662682411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5693163906662682411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5693163906662682411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5693163906662682411'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/05/diagnosing-webappportlet-hot-deploy.html' title='Tomcat and Webapp Hot-deploy Permgen &quot;Leaks&quot;'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8430918617369053413</id><published>2011-05-06T10:28:00.005-04:00</published><updated>2011-05-06T10:30:18.780-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='console command bash linux osx unix'/><title type='text'>Useful *nix One-liners</title><content type='html'>Just got a few notifications about new answers to the question, "&lt;a href="http://www.quora.com/What-are-the-most-useful-swiss-army-knife-one-liners-on-Unix"&gt;What are the most useful "swiss army knife" one-liners on Unix?&lt;/a&gt;" in Quora. Might want to follow it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8430918617369053413?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8430918617369053413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8430918617369053413' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8430918617369053413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8430918617369053413'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/05/useful-nix-one-liners.html' title='Useful *nix One-liners'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1096282920083987338</id><published>2011-03-25T15:03:00.004-04:00</published><updated>2011-05-06T10:09:05.606-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java bug'/><title type='text'>Fixing the parseDouble Bug in Java via Oracle Patch</title><content type='html'>To fix &lt;a href="http://www.infoq.com/news/2011/02/double_bug"&gt;this bug&lt;/a&gt; assuming you have &lt;a href="http://www.oracle.com/technetwork/java/javase/fpupdater-tool-readme-305936.html#systems"&gt;one of the JVMs&lt;/a&gt; that the patch will fix, do the following at your own risk:
&lt;p/&gt;
1. Download fpupdater.zip from &lt;a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html#fpupdater"&gt;http://www.oracle.com/technetwork/java/javase/downloads/index.html#fpupdater&lt;/a&gt;
&lt;p/&gt;
2. Unzip it and copy the fpupdater.jar file contained within the zipped directory to a location on server in a directory you have access to (e.g. /tmp).
&lt;p/&gt;
3. Determine the user that owns the Java install, and sudo to that user or have your admin do that.
&lt;p/&gt;
4. Change to the directory that you copied the file to (e.g. /tmp).
&lt;p/&gt;
5. Test for the bug. (Note: Wherever I just have "java" listed, you may need to call as "/path/to/java/bin/java" if it isn't already in your command path.)&lt;br/&gt;
&lt;pre&gt;&lt;code&gt;
java -jar fpupdater.jar -t -v
&lt;/code&gt;&lt;/pre&gt;
If your JVM has the bug, this will likely produce the result: "Verification test failed; timed out."
&lt;p/&gt;
If your JVM does not have the bug, this will likely produce the result: "Verification test passed." If it says this, there is no need to continue- in fact, you probably shouldn't.
&lt;p/&gt;
If the command fails with something like:
&lt;pre&gt;&lt;code&gt;
Warning: -jar not understood. Ignoring.
Exception in thread "main" java.lang.NoClassDefFoundError: fpupdater.jar
   at _ZN4java4lang11VMThrowable16fillInStackTraceEPNS0_9ThrowableE (/usr/lib64/libgcj.so.5.0.0)
   at _ZN4java4lang9Throwable16fillInStackTraceEv (/usr/lib64/libgcj.so.5.0.0)
   at _ZN4java4lang9ThrowableC1EPNS0_6StringE (/usr/lib64/libgcj.so.5.0.0)
   at _ZN4java4lang5ErrorC1EPNS0_6StringE (/usr/lib64/libgcj.so.5.0.0)
   at _ZN4java4lang12LinkageErrorC1EPNS0_6StringE (/usr/lib64/libgcj.so.5.0.0)
   at _ZN4java4lang20NoClassDefFoundErrorC1EPNS0_6StringE (/usr/lib64/libgcj.so.5.0.0)
   at _ZN3gnu3gcj7runtime11FirstThread3runEv (/usr/lib64/libgcj.so.5.0.0)
   at _Z13_Jv_ThreadRunPN4java4lang6ThreadE (/usr/lib64/libgcj.so.5.0.0)
   at _Z11_Jv_RunMainPN4java4lang5ClassEPKciPS4_b (/usr/lib64/libgcj.so.5.0.0)
   at __gcj_personality_v0 (/tmp/java.version=1.4.2)
   at __libc_start_main (/lib64/tls/libc-2.3.4.so)
   at _Jv_RegisterClasses (/tmp/java.version=1.4.2)
&lt;/code&gt;&lt;/pre&gt;
that probably means that the Java you are using is gcj/GCC Java and not Sun/Oracle Java. Assuming you have a Sun/Oracle Java JVM to update, you may need to call java from the Java location you are trying to update, e.g.:
&lt;pre&gt;&lt;code&gt;
/path/to/java/bin/java -jar fpupdater.jar -t -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
6. Patch it (and if you have to, prepend the path to java, see above.)&lt;/br&gt;
&lt;pre&gt;&lt;code&gt;
java -jar fpupdater.jar -u -v
&lt;/code&gt;&lt;/pre&gt;
It tells you where it backed the old file up to if you use -v, just in case it doesn't work. Be sure to record that somewhere in case you need it.
&lt;p/&gt;
7. Test it again (and if you have to, prepend the path to java, see above.)&lt;/br&gt;
&lt;pre&gt;&lt;code&gt;
java -jar fpupdater.jar -t -v
&lt;/code&gt;&lt;/pre&gt;
This should result in "Verification test passed."
&lt;p/&gt;
8. This is the part you need to handle and I can't really help a lot. You should restart everything, if needed, that uses that version of Java. You could try listing processes that use Java to assist with this (however you do it in your environment):
&lt;pre&gt;&lt;code&gt;
ps auxf|grep java
&lt;/code&gt;&lt;/pre&gt;
But, after that you are on your own about how you want to do that.
&lt;p/&gt;
9. Test everything!
&lt;p/&gt;
Good luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1096282920083987338?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1096282920083987338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1096282920083987338' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1096282920083987338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1096282920083987338'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/03/fixing-parsedouble-bug-in-java-via.html' title='Fixing the parseDouble Bug in Java via Oracle Patch'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6418951332339961566</id><published>2011-03-16T16:00:00.001-04:00</published><updated>2011-05-06T10:09:25.428-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java osx'/><title type='text'>Recovering Lost Java 1.5.0 for Snow Leopard After Java for Mac OS X 10.6 Update 4 Install</title><content type='html'>It looks like Java for Mac OS X 10.6 Update 4 just deleted my /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard directory that I had setup. It is as if Apple assumes that it is ok to delete whatever the /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0 or /System/Library/Frameworks/JavaVM.framework/Versions/1.5 symlinks were pointed to.
&lt;p/&gt;
To get them back:
&lt;pre&gt;&lt;code&gt;
sudo port install wget
cd /tmp/
wget http://tedwise.com/files/java.1.5.0-leopard.tar.gz
tar -zxvf java.1.5.0-leopard.tar.gz
sudo mv 1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard
cd /System/Library/Frameworks/JavaVM.framework/Versions/
sudo rm 1.5.0
sudo ln -s 1.5.0-leopard 1.5.0
sudo ln -s 1.5.0-leopard 1.5
&lt;/code&gt;&lt;/pre&gt;
To get Java 1.4, which it doesn't mess with, but just for completeness:
&lt;pre&gt;&lt;code&gt;
cd /tmp/
wget http://tedwise.com/files/java.1.4.2-leopard.tar.gz
tar -zxvf java.1.4.2-leopard.tar.gz
sudo mv 1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard
cd /System/Library/Frameworks/JavaVM.framework/Versions/
sudo ln -s 1.4.2-leopard 1.4.2
sudo ln -s 1.4.2-leopard 1.4
&lt;/code&gt;&lt;/pre&gt;
This information was originally posted and the binaries hosted by Ted Wise as &amp;quot;&lt;a href="http://tedwise.com/2009/09/25/using-java-1-5-and-java-1-4-on-snow-leopard/"&gt;Using Java 1.5 and Java 1.4 on Snow Leopard&lt;/a&gt;&amp;quot;. Thanks again, Ted!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6418951332339961566?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6418951332339961566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6418951332339961566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6418951332339961566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6418951332339961566'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/03/recovering-lost-java-150-for-snow.html' title='Recovering Lost Java 1.5.0 for Snow Leopard After Java for Mac OS X 10.6 Update 4 Install'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-371630942743280071</id><published>2011-03-15T17:03:00.012-04:00</published><updated>2011-05-06T10:10:22.786-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='https virtual_host shibboleth test testing'/><title type='text'>Requesting a Specific Non-primary Virtual Host via HTTPS Behind Shibboleth</title><content type='html'>To hit a webapp on specific server on a non-default virtual host on non-default SSL port that is load-balanced and behind Shibboleth (or another SSO), you have a go through a few hoops, if you want the normally load-balanced host/port to resolve to that specific host on the specific server, bypassing the load balancer.
&lt;p/&gt;
Setup a SSH tunnel with privileged port 443 locally going to the SSL port of the server for the virtual host you are trying to visit:
&lt;pre&gt;&lt;code&gt;
sudo ssh -L 443:third-foobar-server.acme.org:1443 myuser@third-foobar-server.acme.org
&lt;/code&gt;&lt;/pre&gt;
Then I edited /etc/hosts and pointed foobar.acme.org at 127.0.0.1 by adding the entry:
&lt;pre&gt;&lt;code&gt;
127.0.0.1 foobar.acme.org
&lt;/code&gt;&lt;/pre&gt;
Then you can hit https://foobar.acme.org/ in your browser and bypass the load balancer.
&lt;p/&gt;
This worked in OS X, should work work Linux, and with Putty and the Windows-specific hosts file, it should work there also.
&lt;p/&gt;
In addition, Scott Cantor suggested to me that &lt;a href="http://staff.washington.edu/fox/webisoget/#map"&gt;webisoget&lt;/a&gt;'s map command might be a good way of scripting access to individual shibbolized apps on specific servers more simply, for monitoring, etc.
&lt;p/&gt;
(See also: "&lt;a href="http://serverfault.com/questions/248181/https-request-to-a-specific-load-balanced-virtual-host-using-shibboleth-for-sso"&gt;HTTPS request to a specific load-balanced virtual host (using Shibboleth for SSO)?&lt;/a&gt;".)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-371630942743280071?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/371630942743280071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=371630942743280071' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/371630942743280071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/371630942743280071'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/03/requesting-specific-non-primary-virtual.html' title='Requesting a Specific Non-primary Virtual Host via HTTPS Behind Shibboleth'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-493933597420249362</id><published>2011-03-10T17:38:00.006-05:00</published><updated>2011-05-06T10:08:23.357-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='facebook stream javascript portlet'/><title type='text'>How to Show a Facebook Home News Stream, Friend Requests, and Notifications via Javascript</title><content type='html'>This is a mixture of a number of things I found (and didn't find) out there, although the most helpful was &lt;a href='http://thinkdiff.net/facebook/graph-api-javascript-base-facebook-connect-tutorial/'&gt;Graph api &amp; javascript base Facebook Connect tutorial&lt;/a&gt;, so it is somewhat originally based on that. 
&lt;p/&gt;
This is what it looks like:
&lt;br/&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;div id=&amp;quot;fb-root&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;fb_message&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;!-- Parts of this are based on http://thinkdiff.net/facebook/graph-api-javascript-base-facebook-connect-tutorial/ --&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;

    var application_id = 'replace with your Facebook application id';
    var application_name = 'replace with your Facebook application name';
    
    if (!(application_id)) {
        document.getElementById('fb_message').style.display = &amp;quot;block&amp;quot;;
        document.getElementById('fb_message').innerHTML = &amp;quot;Facebook application_id not defined.&amp;quot;;
    } else if (!(application_name)) {
        document.getElementById('fb_message').style.display = &amp;quot;block&amp;quot;;
        document.getElementById('fb_message').innerHTML = &amp;quot;Facebook application_name not defined.&amp;quot;;
    } else {
        document.getElementById('fb_message').innerHTML = &amp;quot;&amp;quot;;
        document.getElementById('fb_message').style.display = &amp;quot;none&amp;quot;;
    }
    
    var news_results;
    var friends_results;
    var notification_results;
    var friend_request_results;

    window.fbAsyncInit = function() {
        FB.init({
            appId: application_id,
            status: true,
            cookie: true,
            xfbml: true
        });

        /* All the events registered */
        FB.Event.subscribe('auth.login', function(response) {
            // reload the page so news will show
            window.location.reload();
        });
        FB.Event.subscribe('auth.logout', function(response) {
            document.getElementById('fb_status').style.display = &amp;quot;none&amp;quot;;
            document.getElementById('fb_news').style.display = &amp;quot;none&amp;quot;;
            document.getElementById('fb_dashboard').style.display = &amp;quot;none&amp;quot;;
        });

        FB.getLoginStatus(function(response) {
            if (response.session) {
                document.getElementById('fb_news').style.display = &amp;quot;block&amp;quot;;
                document.getElementById('fb_news').innerHTML = &amp;quot;Asking Facebook for latest news from your friends...&amp;quot;;
                var q1 = FB.Data.query(&amp;quot;SELECT created_time, actor_id, message, permalink FROM stream WHERE source_id in (SELECT target_id FROM connection WHERE source_id=me() AND is_following=1) AND strlen(message) &amp;gt; 0 AND is_hidden = 0 limit 5&amp;quot;);
                document.getElementById('fb_news').innerHTML = &amp;quot;Asking Facebook for name and pictures of friends with news...&amp;quot;;
                var q2 = FB.Data.query(&amp;quot;SELECT uid, pic_square, name FROM user WHERE uid IN (SELECT actor_id FROM stream WHERE source_id in (SELECT target_id FROM connection WHERE source_id=me() AND is_following=1) AND strlen(message) &amp;gt; 0 AND is_hidden = 0 limit 5)&amp;quot;);
                document.getElementById('fb_news').innerHTML = &amp;quot;Asking Facebook for number of notifications...&amp;quot;;
                var q3 = FB.Data.query(&amp;quot;SELECT notification_id FROM notification WHERE recipient_id=me() AND is_hidden = 0&amp;quot;);
                document.getElementById('fb_news').innerHTML = &amp;quot;Asking Facebook for number of friend requests...&amp;quot;;
                var q4 = FB.Data.query(&amp;quot;SELECT uid_from FROM friend_request WHERE uid_to=me()&amp;quot;);
                document.getElementById('fb_news').innerHTML = &amp;quot;Waiting on Facebook...&amp;quot;;
                FB.Data.waitOn([q1, q2, q3, q4], function(args) {
                    document.getElementById('fb_news').innerHTML = &amp;quot;Processing Facebook data...&amp;quot;;
                    news_results = args[0];
                    friends_results = args[1];
                    notification_results = args[2];
                    friend_request_results = args[3];
                    displayFacebookData();
                    document.getElementById('fb_dashboard').style.display = &amp;quot;block&amp;quot;;
                    document.getElementById('fb_status').style.display = &amp;quot;block&amp;quot;;
                });
            }
        });

        FB.XFBML.parse();
    };
    (function() {
        var e = document.createElement('script');
        e.type = 'text/javascript';
        e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
        e.async = true;
        document.getElementById('fb-root').appendChild(e);
    }());

    function displayFacebookData() {
        document.getElementById('fb_dashboard').innerHTML = &amp;quot;&amp;lt;table&amp;gt;\n&amp;lt;tbody&amp;gt;\n&amp;lt;tr&amp;gt;\n&amp;quot;;
        document.getElementById('fb_news').innerHTML = &amp;quot;Displaying Facebook notifications...&amp;quot;;
        if (notification_results != null) {
            document.getElementById('fb_dashboard').innerHTML += &amp;quot;&amp;lt;td&amp;gt;&amp;lt;a href='http://www.facebook.com/'&amp;gt;Notifications: &amp;quot; + notification_results.length + &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n&amp;quot;;
        }
        else {
            document.getElementById('fb_dashboard').innerHTML += &amp;quot;&amp;lt;td&amp;gt;&amp;lt;a href='http://www.facebook.com/'&amp;gt;Notifications: None&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n&amp;quot;;
        }
        document.getElementById('fb_news').innerHTML = &amp;quot;Displaying Facebook friend requests...&amp;quot;;

        if (friend_request_results != null) {
            document.getElementById('fb_dashboard').innerHTML += &amp;quot;&amp;lt;td&amp;gt;&amp;lt;a href='http://www.facebook.com/friends/edit/?sk=requests'&amp;gt;Friend Requests: &amp;quot; + friend_request_results.length + &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n&amp;quot;;
        }
        else {
            document.getElementById('fb_dashboard').innerHTML += &amp;quot;&amp;lt;td&amp;gt;&amp;lt;a href='http://www.facebook.com/friends/edit/?sk=requests'&amp;gt;Friend Requests: None&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n&amp;quot;;
        }
        document.getElementById('fb_dashboard').innerHTML += &amp;quot;&amp;lt;/tr&amp;gt;\n&amp;lt;/td&amp;gt;\n&amp;lt;/tbody&amp;gt;\n&amp;lt;/table&amp;gt;\n&amp;quot;;
        document.getElementById('fb_news').innerHTML = &amp;quot;Done preparing Facebook dashboard. Displaying news from friends: &amp;quot; + news_results.length + &amp;quot; news items from &amp;quot; + friends_results.length + &amp;quot; users...&amp;quot;;

        if (!(friends_results.length &amp;gt; 0)) {
            document.getElementById('fb_news').innerHTML = 'No news from friends. &amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;window.location.reload();&amp;quot;&amp;gt;Click here to refresh.&amp;lt;/a&amp;gt;';
        }
        else {
            try {
                var tableHtml = &amp;quot;&amp;quot;;
                tableHtml = '\n&amp;lt;table style=&amp;quot;width:100%;&amp;quot;&amp;gt;\n  &amp;lt;tbody&amp;gt;\n';

                var uidToFriendResult = new Object();
                for (i = 0; i &amp;lt; friends_results.length; i++) {
                    uidToFriendResult[friends_results[i].uid] = friends_results[i];
                }
                for (i = 0; i &amp;lt; news_results.length; i++) {
                    if (i % 2 == 0) {
                        rowClass = 'fb_normal';
                    } else {
                        rowClass = 'fb_alternate';
                    }

                    var friendImageUrl = &amp;quot;img/unknown.gif&amp;quot;;
                    var friendName = &amp;quot;Unknown&amp;quot;;
                    var friendResult = uidToFriendResult[news_results[i].actor_id];
                    if (friendResult != null) {
                        if (friendResult.pic_square != null) {
                            friendImageUrl = friendResult.pic_square;
                        }

                        if (friendResult.name != null) {
                            friendName = friendResult.name;
                        }
                    }

                    var msg = &amp;quot;&amp;quot;;
                    var date = &amp;quot;&amp;quot;;
                    var postUrl = &amp;quot;http://www.facebook.com/?ref=home#permalink-for-post-was-not-supplied-by-facebook&amp;quot;;
                    if (news_results != null &amp;amp;&amp;amp; news_results[i] != null) {
                        if (news_results[i].permalink != null) {
                            postUrl = news_results[i].permalink;
                        }

                        msg = news_results[i].message;
                        if (msg == null) {
                            msg = &amp;quot;&amp;quot;;
                        } else if(msg.length &amp;gt; 160) {
                            msg = msg.substring(0,160)+&amp;quot;... (more)&amp;quot;;
                        }

                        if (news_results[i].created_time != null &amp;amp;&amp;amp; news_results[i].created_time &amp;gt; 0) {
                            var d = new Date();
                            d.setTime(news_results[i].created_time * 1000);
                            var year = d.getFullYear().toString().slice(2);
                            var month = d.getMonth() + 1;
                            if (month &amp;lt; 10) { month = &amp;quot;0&amp;quot; + month; }
                            var date = d.getDate();
                            if (date &amp;lt; 10) { date = &amp;quot;0&amp;quot; + date; }
                            var hour = d.getHours();
                            var ampm = &amp;quot;am&amp;quot;;
                            if (hour &amp;gt; 11) { ampm = &amp;quot;pm&amp;quot;; }
                            if (hour &amp;gt; 12) { hour = hour - 12; }
                            if (hour == 0) { hour = 12; }
                            if (hour &amp;lt; 10) { hour = &amp;quot;0&amp;quot; + hour; }
                            var minutes = d.getMinutes();
                            if (minutes &amp;lt; 10) { minutes = &amp;quot;0&amp;quot; + minutes; }
                            date = month + &amp;quot;/&amp;quot; + date + &amp;quot;/&amp;quot; + year + &amp;quot; &amp;quot; + hour + &amp;quot;:&amp;quot; + minutes + ampm;
                        }
                    }
                    tableHtml += &amp;quot;    &amp;lt;tr class='&amp;quot;;
                    tableHtml += rowClass;
                    tableHtml += &amp;quot;'&amp;gt;\n      &amp;lt;td&amp;gt;&amp;lt;a href='&amp;quot; + postUrl + &amp;quot;' target='_blank'&amp;gt;&amp;lt;img src='&amp;quot;;
                    tableHtml += friendImageUrl;
                    tableHtml += &amp;quot;' alt='&amp;quot;;
                    tableHtml += friendName;
                    tableHtml += &amp;quot;' title='&amp;quot;;
                    tableHtml += friendName;
                    tableHtml += &amp;quot;' style='width:auto; height:20px;'/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;&amp;lt;a href='&amp;quot; + postUrl + &amp;quot;' target='_blank'&amp;gt;&amp;quot;;
                    tableHtml += friendName;
                    tableHtml += &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;&amp;lt;a href='&amp;quot; + postUrl + &amp;quot;' target='_blank'&amp;gt;&amp;quot;;
                    tableHtml += msg;
                    tableHtml += &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;&amp;lt;span style='white-space: nowrap;'&amp;gt;&amp;lt;a href='&amp;quot; + postUrl + &amp;quot;' target='_blank'&amp;gt;&amp;quot;;
                    tableHtml += date;
                    tableHtml += &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;\n&amp;quot;;
                }
                tableHtml += '  &amp;lt;/tbody&amp;gt;\n&amp;lt;/table&amp;gt;\n';

                document.getElementById('fb_news').innerHTML = tableHtml;
            } catch (e) {
                var errorMsg = '';
                for (var property in e) {
                    errorMsg += property + ': ' + e[property] + '\r\n';
                }
                document.getElementById('fb_news').innerHTML = &amp;quot;&amp;lt;pre&amp;gt;&amp;quot; + errorMsg + &amp;quot;&amp;lt;/pre&amp;gt;&amp;quot;;
            }
        }
    }

    function setStatus() {
        status1 = document.getElementById('fb_status_text').value;
        FB.api({
            method: 'status.set',
            status: status1
        }, function(response) {
            if (response == 0) {
                alert('Your Facebook status was not updated. In your Facebook profile\'s privacy settings, remove ' + my_facebook_application + ' from your privacy settings, go back to this page, login, and agree to give the application the required privacy settings.');
            } else {
                alert('Your Facebook status was updated');
            }
        });
    }
&amp;lt;/script&amp;gt;
&amp;lt;p&amp;gt;
    &amp;lt;fb:login-button autologoutlink=&amp;quot;true&amp;quot; perms=&amp;quot;status_update,publish_stream,read_stream,offline_access&amp;quot;&amp;gt;
    &amp;lt;/fb:login-button&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div id=&amp;quot;fb_dashboard&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;fb_news&amp;quot;&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;window.location.reload();&amp;quot;&amp;gt;Click here to refresh news&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&amp;quot;fb_status&amp;quot;&amp;gt;
&amp;lt;textarea id=&amp;quot;fb_status_text&amp;quot; cols=&amp;quot;50&amp;quot; rows=&amp;quot;2&amp;quot; placeholder=&amp;quot;Post status to Facebook&amp;quot;&amp;gt;
&amp;lt;/textarea&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;Post Status to Facebook&amp;quot; onclick=&amp;quot;setStatus(); return false;&amp;quot;/&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
&lt;em&gt;Edit: Now part of the &lt;a href="https://source.jasig.org/sandbox/FacebookPortlet/tags/rel-2.0-alpha-1/src/main/webapp/WEB-INF/jsp/view.jsp"&gt;Facebook Portlet v2.0&lt;/a&gt;.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-493933597420249362?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/493933597420249362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=493933597420249362' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/493933597420249362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/493933597420249362'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/03/how-show-facebook-home-news-stream.html' title='How to Show a Facebook Home News Stream, Friend Requests, and Notifications via Javascript'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1139688745429629069</id><published>2011-02-16T13:49:00.007-05:00</published><updated>2011-05-06T10:11:22.438-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java analysis profiling thread dump jstack jda jconsole visualvm'/><title type='text'>Java Thread Dumps, JStack, JDA, JConsole, VisualVM</title><content type='html'>Eric D. and Chuck Frank on the uPortal list were discussing Java dumps and analysis. Eric suggested that he does at least three Java thread dumps spaced 30 seconds apart and then analyzes them. Between the two they mentioned:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html"&gt;JStack&lt;/a&gt; to dump (or kill -3 (pid) on *nix)
&lt;li&gt;&lt;a href="http://java.net/projects/tda/downloads"&gt;TDA&lt;/a&gt; for Java thread dump analysis
&lt;li&gt;&lt;a href="http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html"&gt;JConsole&lt;/a&gt; for JVM monitoring in Java 5+
&lt;/ul&gt;
To add some others:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/index.html"&gt;VisualVM&lt;/a&gt; included in Java 6 update 7 (on OS X was included in Mac OS X 10.5 Update 4)
&lt;li&gt;&lt;a href="http://java-source.net/open-source/profilers"&gt;Open Source Profilers in Java&lt;/a&gt;
&lt;/ul&gt;
But, I am guessing that the point of sample dumps vs. using a profiler was due to what was mentioned by Mike Dunlavey &lt;a href="http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343"&gt;here&lt;/a&gt; and &lt;a href="http://stackoverflow.com/questions/375913/what-can-i-use-to-profile-c-code-in-linux/378024#378024"&gt;here&lt;/a&gt;. Good reads, btw.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1139688745429629069?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1139688745429629069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1139688745429629069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1139688745429629069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1139688745429629069'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/02/java-thread-dumps-jstack-jda-jconsole.html' title='Java Thread Dumps, JStack, JDA, JConsole, VisualVM'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2475940954432758784</id><published>2011-02-08T11:28:00.014-05:00</published><updated>2011-05-06T10:11:48.629-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby error before_filter'/><title type='text'>DoubleRenderError and :before_filter</title><content type='html'>&lt;pre&gt;&lt;code&gt;
A ActionController::DoubleRenderError occurred in 
(some action):

Render and/or redirect were called multiple times 
in this action. Please note that you may only call 
render OR redirect, and at most once per action. 
Also note that neither redirect nor render 
terminate execution of the action, so if you want 
to exit an action after redirecting, you need to 
do something like "redirect_to(...) and return".
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
When you get a DoubleRenderError, there is a good chance that something is happening as part of an action that you didn't anticipate, because you expected all action to stop when you did a render or redirect_to. So, bad things may be happening, like ignoring authentication, executing the action anyway, and then displaying to the user that either that he was unauthorized or displaying a page that is the result of a DoubleRenderError.
&lt;p/&gt;
One cause of this is particularly insidious. :before_filter keeps track of whether a render or redirect_to was called and, if so, will stop the action. If you move a method previously called by the :before_filter to the action method itself, you may forget to return from the action if that method calls render or redirect_to. If you are lucky there will be another render or redirect_to and this will result in a DoubleRenderError, so you'll catch it and perhaps be alerted that something went wrong. However, an action getting executed unintentionally is not a good thing.
&lt;p/&gt;
To avoid this, be sure that when you call a method that might render or redirect for that method to return a boolean that you can use in the calling method to return from the action.
&lt;p/&gt;
The following authenticate method is fine when called by a :before_filter:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
class MyController &lt; ApplicationController

  :before_filter authenticate

  def authenticate
    render :file =&gt; "public/401.html", :status =&gt; :unauthorized unless authorized?
  end

  def some_action
    # do something important and possibly render or redirect_to
  end

end
&lt;/code&gt;&lt;/pre&gt;
However, after moving this to the action method, you need to do a return:
&lt;pre&gt;&lt;code&gt;
class MyController &lt; ApplicationController

  def authenticate
    auth = authorized?
    render :file =&gt; "public/401.html", :status =&gt; :unauthorized unless auth
    return auth
  end

  def some_action
    return unless authenticate
    # do something important and possibly render or redirect_to
  end

  def some_other_action
    # this action is not authenticated or is authenticated differently,
    # but still makes sense to include in this controller
  end

end
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2475940954432758784?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2475940954432758784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2475940954432758784' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2475940954432758784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2475940954432758784'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/02/doublerendererror-and-beforefilter.html' title='DoubleRenderError and :before_filter'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-97147949381483371</id><published>2011-01-21T09:39:00.007-05:00</published><updated>2011-05-06T10:13:23.253-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx linux unix console file directory size human readable du sort df cli bash'/><title type='text'>OS X/Linux Command to Display Total Size of All Directories and Subdirectories Within Current Directory</title><content type='html'>Jim just taught me this, which rolls up the sizes of subdirectories to provide a total size of each directories in the current directory in *nix:
&lt;pre&gt;&lt;code&gt;
du -sch *
&lt;/code&gt;&lt;/pre&gt;
I'd used 'du -h' before quite a bit which shows sizes throughout directories recursively. With larger directories, it is helpful to sort and axe the human-readable sizes with 'du -sk * | sort -nr'. 'df -H' is also very helpful to show volume sizes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-97147949381483371?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/97147949381483371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=97147949381483371' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/97147949381483371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/97147949381483371'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/01/os-xlinux-command-to-display-total-size.html' title='OS X/Linux Command to Display Total Size of All Directories and Subdirectories Within Current Directory'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1593824698485667625</id><published>2011-01-20T17:21:00.002-05:00</published><updated>2011-05-06T10:13:41.148-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog stats'/><title type='text'>Styho Blog Post Stats</title><content type='html'>Had a few minutes waiting on a process to finish, so used Excel to graph some blog posting stats.
&lt;p/&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_dkSPoUrJq0E/TTi1HvnpomI/AAAAAAAAEH0/NzJSMsgaOtg/s1600/posts%2Bper%2Bmonth%2B2011-01-20.png" imageanchor="1" style=""&gt;&lt;img border="0" height="240" width="400" src="http://2.bp.blogspot.com/_dkSPoUrJq0E/TTi1HvnpomI/AAAAAAAAEH0/NzJSMsgaOtg/s400/posts%2Bper%2Bmonth%2B2011-01-20.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1593824698485667625?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1593824698485667625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1593824698485667625' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1593824698485667625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1593824698485667625'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/01/styho-blog-post-stats.html' title='Styho Blog Post Stats'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_dkSPoUrJq0E/TTi1HvnpomI/AAAAAAAAEH0/NzJSMsgaOtg/s72-c/posts%2Bper%2Bmonth%2B2011-01-20.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1756105272761259562</id><published>2011-01-07T09:52:00.010-05:00</published><updated>2011-01-07T09:58:55.899-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='schema sleuth ssleuth find related data automatically oracle dbi unix osx'/><title type='text'>Schema Sleuth Finds Related Data Automatically</title><content type='html'>Just wrote &lt;a href="https://github.com/garysweaver/schema-sleuth"&gt;Schema Sleuth&lt;/a&gt; to help "spider" a database or schema to find all related data, and to output it to the console as text-based representations of partial tables or SQL inserts. In my case, I wanted everything related to a User ID and its related data, but it can find almost any subset of related data easily. It's written to be called as a Ruby command-line/CLI script in *nix. Tested with OS X against a few Oracle schemas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1756105272761259562?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1756105272761259562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1756105272761259562' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1756105272761259562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1756105272761259562'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2011/01/schema-sleuth-finds-related-data.html' title='Schema Sleuth Finds Related Data Automatically'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6540132739757672931</id><published>2010-12-21T14:27:00.007-05:00</published><updated>2011-01-24T22:07:21.801-05:00</updated><title type='text'>Easily View Logs, Changesets, and Authors in Git, Mercurial, and Subversion from Terminal.app in OS X</title><content type='html'>I like doing most of my SCM/VCS work in Terminal.app, but when I want to look at logs and the diffs in their changesets for commits, I like a UI.
&lt;p/&gt;
GitX is great at this. If you've installed Git or have it already, install &lt;a href="http://gitx.frim.nl/"&gt;GitX&lt;/a&gt;, start it, and in the menu do "GitX -&amp;gt; Enable Terminal Usage". Restart Terminal.app, browse to a Git repository, and type the following to see the log:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
gitx
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Subversion was a little trickier. Assuming you've installed Subversion or have it already, install &lt;a href="http://code.google.com/p/svnx/"&gt;SvnX&lt;/a&gt;. Start the application once and it will put the svnx shell script into your ~/bin/svnx. Assuming you don't have ~/bin/ on path, you can add the following to your ~/bash_profile:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
alias svnx='~/bin/svnx wc . &amp;&amp; ~/bin/svnx log .'
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
After restarting Terminal.app, browse to a checked-out subversion repository and just type the following to see a log:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
svnx
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Mercurial is a little tricky, but mostly because the tool I use is called Murky, not hgx, as you might think. Hgx is easier to remember, that is what I call my alias. Assuming you've installed subversion or have it already, install &lt;a href="https://bitbucket.org/snej/murky/wiki/Home"&gt;Murky&lt;/a&gt;. Then, add the following to your ~/bash_profile:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
alias hgx='open -a Murky .'
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
After restarting Terminal.app, browse to a checked-out Mercurial repository and type the following to see its log:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
hgx
&lt;/code&gt;&lt;/pre&gt;
(&lt;a href="https://bitbucket.org/snej/murky/issue/171/terminal-integration"&gt;Thanks to Jens Alfke for the Mercurial command-line solution&lt;/a&gt;.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6540132739757672931?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6540132739757672931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6540132739757672931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6540132739757672931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6540132739757672931'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/12/easily-view-logs-changesets-and-authors.html' title='Easily View Logs, Changesets, and Authors in Git, Mercurial, and Subversion from Terminal.app in OS X'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7436533511613673640</id><published>2010-12-03T10:24:00.007-05:00</published><updated>2010-12-03T10:29:09.098-05:00</updated><title type='text'>Type of Plane and Seats for Airline by Flight #</title><content type='html'>Check out &lt;a href="http://www.seatguru.com/"&gt;SeatGuru&lt;/a&gt;. While many airlines have seat maps online that you can view after you've chosen the flight based on date, time, and price, I've often wished that I could have chosen the type of plane also. With SeatGuru, you can. And, you can even find by route. (Thanks to &lt;a href="http://blogs.atlassian.com/developer/2010/12/time_for_change_joining_atlassian_in_sydney.html"&gt;this post&lt;/a&gt; on the Atlassian Developer Blog for the reference.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7436533511613673640?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7436533511613673640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7436533511613673640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7436533511613673640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7436533511613673640'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/12/type-of-plane-and-seats-for-airline-by.html' title='Type of Plane and Seats for Airline by Flight #'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6709501478295118833</id><published>2010-11-11T14:40:00.002-05:00</published><updated>2010-11-11T14:47:36.717-05:00</updated><title type='text'>Automate Terminal.app ~/.login.sh Script on Login in OS X 10.6 to Mount TrueCrypt Volume, etc.</title><content type='html'>&lt;a href="http://www.truecrypt.org/"&gt;TrueCrypt&lt;/a&gt; is nice, but it doesn't currently have a way in OS X to automatically ask for just your password at login. I first wrote a simple Applescript in AppleScript Editor:
&lt;pre&gt;&lt;code&gt;
do script &amp;quot;/Applications/TrueCrypt.app/Contents/MacOS/TrueCrypt /path/to/volume/file/volume.tc /path/to/dir/my_encrypted_dir&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
then File &amp;gt; Save As... &amp;gt; File Format: Application and saved to the Applications directory. Then I went to System Preferences -&amp;gt; Accounts -&amp;gt; (choose user) -&amp;gt; Login Items and added that new script (application) there, so it would start automatically after Login.
&lt;p/&gt;
But, this pops up a UI that gives you the option to use password or key files. I only wanted to provide a password. I also thought it would be cool to have a shell script to run on OS X login in Terminal.app that I could keep in my home directory and modify at will with a text editor rather than AppleScript Editor.
&lt;p/&gt;
So, I wrote the following AppleScript in AppleScript Editor and again used File &amp;gt; Save As... &amp;gt; File Format: Application to the Applications directory. Then went to System Preferences -&amp;gt; Accounts -&amp;gt; (choose user) -&amp;gt; Login Items and added that new script (application) there, so it would start automatically after Login. (I also removed the other one I'd created.)
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
tell application &amp;quot;System Events&amp;quot;
 set terminal_is_open to (exists process &amp;quot;Terminal&amp;quot;)
end tell

tell application &amp;quot;Terminal&amp;quot;
 activate
 if terminal_is_open then
  tell application &amp;quot;System Events&amp;quot; to tell process &amp;quot;Terminal&amp;quot; to keystroke &amp;quot;n&amp;quot; using command down
 end if
 do script with command &amp;quot;~/.login.sh&amp;quot; in selected tab of the front window
end tell
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then I created a file ~/.login.sh containing:
&lt;pre&gt;&lt;code&gt;
#/usr/sh

# Things to run on login...
clear

# Mount encrypted volume
/Applications/TrueCrypt.app/Contents/MacOS/TrueCrypt -t -k &amp;quot;&amp;quot; --protect-hidden=no /path/to/volume/file/volume.tc /path/to/dir/my_encrypted_dir
&lt;/code&gt;&lt;/pre&gt;
Then I did:
&lt;pre&gt;&lt;code&gt;
chmod +x ~/.login.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Logout, login, and it should display a Terminal.app window prompting you for your password to the TrueCrypt volume. After that, I just leave the window open in case there is an error.
&lt;p/&gt;
Note that to rename the TrueCrypt volume mount on the desktop, just rename it like any other file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6709501478295118833?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6709501478295118833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6709501478295118833' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6709501478295118833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6709501478295118833'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/11/automate-terminalapp-loginsh-script-on.html' title='Automate Terminal.app ~/.login.sh Script on Login in OS X 10.6 to Mount TrueCrypt Volume, etc.'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5668646846150141260</id><published>2010-11-04T16:47:00.007-04:00</published><updated>2010-11-04T17:04:15.953-04:00</updated><title type='text'>Time Equivalence or Closeness in RSpec</title><content type='html'>If you have two times in RSpec that you want to make sure are equal, you could use:
&lt;pre&gt;&lt;code&gt;
kid.sleepy_at.should eq(bedtime)
&lt;/code&gt;&lt;/pre&gt;
But, that only checks to make sure that the time to the nearest second is equal.
&lt;p/&gt;
To be more exact than a rounded second use:
&lt;pre&gt;&lt;code&gt;
kid.sleepy_at.to_f.should eq(bedtime.to_f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
If you want to ensure that a time is just close to the expected time, use &lt;a href="http://apidock.com/rspec/Spec/Matchers/be_close"&gt;be_close&lt;/a&gt;.
&lt;p/&gt;
For example, if sleepy_at should be within a half second of bedtime use:
&lt;pre&gt;&lt;code&gt;
kid.sleepy_at.to_f.should be_close(bedtime.to_f, 0.5)
&lt;/code&gt;&lt;/pre&gt;
Converting time to float with to_f doesn't look pretty when it fails, but if you don't use it, and use:
&lt;pre&gt;&lt;code&gt;
kid.sleepy_at.should be_close(bedtime, 0.5)
&lt;/code&gt;&lt;/pre&gt;
then it is comparing seconds, and you might get an error like:
&lt;pre&gt;&lt;code&gt;
Failure/Error: kid.sleepy_at.should be_close(bedtime, 0.5)
expected Thu Nov 04 20:50:21 UTC 2010 +/- (&lt; 0.5), got 2010-11-04 20:50:22 UTC
&lt;/code&gt;&lt;/pre&gt;
This is due to the second being rounded off.
&lt;p/&gt;
To make sure they are within a rounded second of each other, use:
&lt;pre&gt;&lt;code&gt;
kid.sleepy_at.should be_close(bedtime, 1)
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5668646846150141260?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5668646846150141260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5668646846150141260' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5668646846150141260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5668646846150141260'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/11/time-equivalence-or-closeness-in-rspec.html' title='Time Equivalence or Closeness in RSpec'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4350563038010817707</id><published>2010-10-27T11:21:00.003-04:00</published><updated>2010-10-27T11:32:19.075-04:00</updated><title type='text'>Resizing Cross-domain Content in an iFrame in YouTube Video Embeds</title><content type='html'>Saw the post, "&lt;a href="http://blog.mefeedia.com/html5-oct-2010"&gt;HTML5 Video Available on the Web – October Update&lt;/a&gt;" by Frank Sinton, which linked to YouTube's beta support for embedding via iFrame. I noticed that the linked YouTube post, "&lt;a href="http://apiblog.youtube.com/2010/07/new-way-to-embed-youtube-videos.html"&gt;A New Way To Embed YouTube Videos&lt;/a&gt;", was in a different domain than the embedded video. So, I looked a little deeper.
&lt;p/&gt;
I chose a currently popular Monty Python &lt;a href="http://www.youtube.com/embed/ZNeq2Utm0nU"&gt;video clip&lt;/a&gt; from Life of Brian, and looked at the HTML (as of 2010-10-27):
&lt;pre&gt;&lt;code&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;YouTube - Monty Python's - Life of Brian-5&amp;lt;/title&amp;gt;

  &amp;lt;style&amp;gt;
    body {
      font: 12px Arial, sans-serif;
      background-color: #000000;
      color: #FFFFFF;
      height: 100%;
      width: 100%;
      margin: 0;
      overflow: hidden;
    }
  &amp;lt;/style&amp;gt;
    
    &amp;lt;script  src=&amp;quot;http://s.ytimg.com/yt/jsbin/www-embed-vflqRiLRQ.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div id=&amp;quot;watch-longform-ad&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;

    &amp;lt;div id=&amp;quot;watch-longform-text&amp;quot;&amp;gt;
Advertisement
    &amp;lt;/div&amp;gt;
    &amp;lt;div id=&amp;quot;watch-longform-ad-placeholder&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; height=&amp;quot;60&amp;quot; width=&amp;quot;300&amp;quot; /&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

    &amp;lt;div id=&amp;quot;html5-player-css-holder&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div id=&amp;quot;embed-holder&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;watch-player-div&amp;quot; class=&amp;quot;flash-player&amp;quot; style=&amp;quot;position: absolute; width:100%; height:100%;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div id=&amp;quot;video-player&amp;quot; class=&amp;quot;html5-video-player&amp;quot; tabindex=&amp;quot;0&amp;quot;&amp;gt;

    &amp;lt;div class=&amp;quot;video-fallback&amp;quot; style=&amp;quot;display: none;&amp;quot;&amp;gt;
      Your browser does not currently recognize any of the video formats available.&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;/html5&amp;quot;&amp;gt;Click here to visit our frequently asked questions about HTML5 video.&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id=&amp;quot;captions&amp;quot; class=&amp;quot;video-captions&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;captions-holder&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;captions-text&amp;quot; class=&amp;quot;hidden&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;video-content&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;html5-video-loader html5-center-overlay html5-icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;svg class=&amp;quot;html5-big-play-button html5-center-overlay&amp;quot;&amp;gt;

          &amp;lt;g opacity=&amp;quot;0.4&amp;quot;&amp;gt;
            &amp;lt;path fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#FFFFFF&amp;quot; stroke-width=&amp;quot;3&amp;quot; stroke-linecap=&amp;quot;round&amp;quot; stroke-linejoin=&amp;quot;round&amp;quot; d=&amp;quot;M88.34,9.698
              c-1.09-1.04-2.43-1.62-3.92-1.8c-23.061-1.44-46.08-1.44-69.14,0c-1.48,0.18-2.72,0.76-3.84,1.8c-1.09,1.04-1.81,2.27-2.14,3.78
              c-1.05,7.07-1.56,14.17-1.56,21.26c0,7.21,0.51,14.27,1.56,21.34c0.33,1.51,1.05,2.74,2.14,3.779c1.12,1.051,2.36,1.621,3.84,1.801
              c23.06,1.439,46.08,1.439,69.14,0c1.49-0.18,2.83-0.75,3.92-1.801c1.12-1.039,1.77-2.34,2.1-3.819
              C91.46,48.938,92,41.878,92,34.738c0-7.09-0.54-14.16-1.561-21.22C90.109,12.038,89.46,10.818,88.34,9.698z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;
          &amp;lt;/g&amp;gt;
          &amp;lt;g class=&amp;quot;html5-overlay-button-background&amp;quot; opacity=&amp;quot;0.8&amp;quot;&amp;gt;
            &amp;lt;path d=&amp;quot;M88.34,9.698c-1.09-1.04-2.43-1.62-3.92-1.8c-23.061-1.44-46.08-1.44-69.14,0c-1.48,0.18-2.72,0.76-3.84,1.8
              c-1.09,1.04-1.81,2.27-2.14,3.78c-1.05,7.07-1.56,14.17-1.56,21.26c0,7.21,0.51,14.27,1.56,21.34c0.33,1.51,1.05,2.74,2.14,3.779
              c1.12,1.051,2.36,1.621,3.84,1.801c23.06,1.439,46.08,1.439,69.14,0c1.49-0.18,2.83-0.75,3.92-1.801
              c1.12-1.039,1.77-2.34,2.1-3.819C91.46,48.938,92,41.878,92,34.738c0-7.09-0.54-14.16-1.561-21.22
              C90.109,12.038,89.46,10.818,88.34,9.698z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;
          &amp;lt;/g&amp;gt;
          &amp;lt;path opacity=&amp;quot;0.19&amp;quot; fill=&amp;quot;#FFFFFF&amp;quot; enable-background=&amp;quot;new&amp;quot; d=&amp;quot;M88.34,9.698c-1.09-1.04-2.43-1.62-3.92-1.8
            c-23.061-1.44-46.08-1.44-69.14,0c-1.48,0.18-2.72,0.76-3.84,1.8c-1.09,1.04-1.81,2.27-2.14,3.78c-1.05,7.07-1.56,14.17-1.56,21.26
            c0,7.21,1.49,21.949,1.56,21.34c30.89-29.62,44.3-5.48,81.14-42.56C91.51,12.438,89.46,10.818,88.34,9.698z&amp;quot;&amp;gt;&amp;lt;/path&amp;gt;
          &amp;lt;g class=&amp;quot;html5-overlay-button-background&amp;quot; opacity=&amp;quot;0.66&amp;quot;&amp;gt;
            &amp;lt;polygon fill=&amp;quot;#FFFFFF&amp;quot; points=&amp;quot;39.32,16.729 39.32,52.798 68.18,34.168&amp;quot;&amp;gt;&amp;lt;/polygon&amp;gt;

          &amp;lt;/g&amp;gt;
        &amp;lt;/svg&amp;gt;
      &amp;lt;ul class=&amp;quot;html5-context-menu yt-uix-button-menu hid&amp;quot;&amp;gt;
        &amp;lt;li&amp;gt;
          &amp;lt;a class=&amp;quot;yt-uix-button-menu-item&amp;quot; target=&amp;quot;_blank&amp;quot; href=&amp;quot;http://www.youtube.com/watch?v=dQw4w9WgXcQ&amp;quot;&amp;gt;Save Video As...&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;
          &amp;lt;a class=&amp;quot;yt-uix-button-menu-item&amp;quot; href=&amp;quot;/html5&amp;quot;&amp;gt;About HTML5&amp;lt;/a&amp;gt;

        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;video-controls&amp;quot; style=&amp;quot;display: none;&amp;quot;&amp;gt;
      &amp;lt;img class=&amp;quot;html5-watermark html5-stop-propagation html5-icon&amp;quot; src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; alt=&amp;quot;watermark&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;html5-progress-bar html5-stop-propagation&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;html5-scrubber-button html5-progress-item html5-icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;html5-progress-list html5-progress-item&amp;quot;&amp;gt;
          &amp;lt;div class=&amp;quot;html5-play-progress html5-progress-section&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;

          &amp;lt;div class=&amp;quot;html5-load-progress html5-progress-section&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&amp;quot;html5-player-chrome html5-stop-propagation&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;html5-play-button html5-button html5-control&amp;quot;&amp;gt;
          &amp;lt;input type=&amp;quot;image&amp;quot; class=&amp;quot;html5-icon&amp;quot; src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; alt=&amp;quot;Play/Pause&amp;quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;html5-volume-control html5-control yt-uix-tooltip&amp;quot; tabindex=&amp;quot;0&amp;quot; title=&amp;quot;Mute&amp;quot; data-alt-title=&amp;quot;Unmute&amp;quot;&amp;gt;
          &amp;lt;div class=&amp;quot;html5-volume-button html5-button&amp;quot; data-value=&amp;quot;loud&amp;quot;&amp;gt;

            &amp;lt;input type=&amp;quot;image&amp;quot; class=&amp;quot;html5-icon&amp;quot; src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div class=&amp;quot;html5-volume-panel&amp;quot;&amp;gt;
            &amp;lt;div class=&amp;quot;html5-volume-slider html5-icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;progress-text html5-control&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;current-time&amp;quot;&amp;gt;00:00&amp;lt;/span&amp;gt;&amp;lt;span&amp;gt; / &amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;duration-time&amp;quot;&amp;gt;00:00&amp;lt;/span&amp;gt;

        &amp;lt;/div&amp;gt;

        &amp;lt;div class=&amp;quot;html5-fullscreen-button html5-button html5-control html5-control-right yt-uix-tooltip&amp;quot; data-value=&amp;quot;fullscreen&amp;quot; title=&amp;quot;Full screen&amp;quot; data-alt-title=&amp;quot;Exit full screen&amp;quot;&amp;gt;
          &amp;lt;input type=&amp;quot;image&amp;quot; class=&amp;quot;html5-icon&amp;quot; src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; alt=&amp;quot;Full screen&amp;quot;&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;html5-captions-button html5-button-popup-menu html5-control html5-control-right&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;html5-button-label html5-empty-label&amp;quot;&amp;gt;
            &amp;lt;input type=&amp;quot;image&amp;quot; class=&amp;quot;html5-icon&amp;quot; src=&amp;quot;http://s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif&amp;quot; alt=&amp;quot;Subtitles&amp;quot;&amp;gt;
          &amp;lt;/span&amp;gt;

        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;html5-quality-button html5-button-popup-menu html5-control html5-control-right&amp;quot; title=&amp;quot;Quality&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;html5-button-label&amp;quot;&amp;gt;360p&amp;lt;/span&amp;gt;
          &amp;lt;ul class=&amp;quot;html5-quality-popup-menu html5-popup-menu&amp;quot;&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;1080p&amp;quot;&amp;gt;
              1080p &amp;lt;sup&amp;gt;HD&amp;lt;/sup&amp;gt;
            &amp;lt;/li&amp;gt;

            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;720p&amp;quot;&amp;gt;
              720p &amp;lt;sup&amp;gt;HD&amp;lt;/sup&amp;gt;
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;480p&amp;quot;&amp;gt;
              480p
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;360p&amp;quot;&amp;gt;
              360p
            &amp;lt;/li&amp;gt;

          &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;html5-speed-button html5-button-popup-menu html5-control html5-control-right&amp;quot; title=&amp;quot;Speed&amp;quot;&amp;gt;
          &amp;lt;span class=&amp;quot;html5-button-label&amp;quot;&amp;gt;Normal&amp;lt;/span&amp;gt;
          &amp;lt;ul class=&amp;quot;html5-speed-popup-menu html5-popup-menu&amp;quot;&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;2.0&amp;quot;&amp;gt;
2x Speed
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;1.5&amp;quot;&amp;gt;

1.5x Speed
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;1.0&amp;quot;&amp;gt;
Normal Speed
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;0.5&amp;quot;&amp;gt;
&amp;amp;frac12; Speed
            &amp;lt;/li&amp;gt;
            &amp;lt;li class=&amp;quot;html5-popup-menu-item&amp;quot; data-value=&amp;quot;0.25&amp;quot;&amp;gt;
&amp;amp;frac14; Speed
            &amp;lt;/li&amp;gt;
          &amp;lt;/ul&amp;gt;

        &amp;lt;/div&amp;gt;
        &amp;lt;a class=&amp;quot;html5-control html5-control-right html5-control-last html5-player-branding&amp;quot; href=&amp;quot;/html5&amp;quot;&amp;gt;
          HTML5
        &amp;lt;/a&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;/div&amp;gt;

  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
  var playerElementId = &amp;quot;&amp;quot;;

  var writeFlashEmbed = function() {
    var video_url = &amp;quot;http://www.youtube.com/v/ZNeq2Utm0nU?showinfo=0&amp;amp;amp;enablejsapi=1&amp;amp;amp;version=3&amp;amp;amp;et=OEgsToPDskKqrAsC70ymD-QZmm4A977Q&amp;amp;amp;iurl=http%3A%2F%2Fi3.ytimg.com%2Fvi%2FZNeq2Utm0nU%2Fhqdefault.jpg&amp;amp;amp;el=embedded&amp;amp;amp;use_native_controls=False&amp;amp;amp;video_id=ZNeq2Utm0nU&amp;amp;amp;autohide=0&amp;amp;amp;hl=en_US&amp;amp;amp;eurl=&amp;amp;amp;autoplay=0&amp;quot;;
    var fo = new SWFObject(video_url, &amp;quot;movie_player&amp;quot;, &amp;quot;100%&amp;quot;, &amp;quot;100%&amp;quot;, &amp;quot;7&amp;quot;, &amp;quot;#000000&amp;quot;);
    var startTime = yt.www.watch.player.processLocationHashSeekTime();
    if (window.opener
      &amp;amp;&amp;amp; window.opener.yt
      &amp;amp;&amp;amp; window.opener.yt.getConfig
      &amp;amp;&amp;amp; window.opener.yt.getConfig('SEQUENTIAL_VIDEO_LIST')) {
      fo.addVariable(&amp;quot;playlist&amp;quot;, window.opener.yt.getConfig('SEQUENTIAL_VIDEO_LIST'));
    }
    fo.addParam(&amp;quot;allowFullscreen&amp;quot;, &amp;quot;true&amp;quot;);
    fo.addParam(&amp;quot;AllowScriptAccess&amp;quot;, &amp;quot;always&amp;quot;);

    if (startTime) {
      fo.addVariable('start', startTime);
    }
    fo.write(&amp;quot;watch-player-div&amp;quot;);

    playerElementId = &amp;quot;movie_player&amp;quot;;

      handleResize = function() {
    var windowHeight = window.innerHeight;
    var adjustedHeight = windowHeight - _gel('watch-longform-ad').offsetHeight;
    var percentHeight = Math.round((adjustedHeight * 100) / windowHeight) + &amp;quot;%&amp;quot;;
    _gel('watch-player-div').style.height = percentHeight;
  }
  yt.events.listen(window, 'resize', handleResize);
  yt.events.listen(_gel('watch-longform-ad-placeholder'), 'resize', handleResize);

  };

  var writeHtml5Embed = function(availableFormats) {
    document.getElementById(&amp;quot;html5-player-css-holder&amp;quot;).innerHTML = &amp;quot;  &amp;lt;link  rel=\&amp;quot;stylesheet\&amp;quot; href=\&amp;quot;http:\/\/s.ytimg.com\/yt\/cssbin\/www-player-vflbyieqp.css\&amp;quot;&amp;gt;\n&amp;quot;;

    var startTime = yt.www.watch.player.processLocationHashSeekTime();

    var videoPlayer = new yt.player.VideoPlayer();
    videoPlayer.setAvailableFormats(availableFormats);

    var playerVars = {&amp;quot;iurl&amp;quot;: &amp;quot;http:\/\/i3.ytimg.com\/vi\/ZNeq2Utm0nU\/hqdefault.jpg&amp;quot;, &amp;quot;el&amp;quot;: &amp;quot;embedded&amp;quot;, &amp;quot;use_native_controls&amp;quot;: false, &amp;quot;video_id&amp;quot;: &amp;quot;ZNeq2Utm0nU&amp;quot;, &amp;quot;autohide&amp;quot;: &amp;quot;0&amp;quot;, &amp;quot;hl&amp;quot;: &amp;quot;en_US&amp;quot;, &amp;quot;eurl&amp;quot;: &amp;quot;&amp;quot;, &amp;quot;autoplay&amp;quot;: &amp;quot;0&amp;quot;};
    if (startTime) {
      playerVars['start'] = startTime;
    }
    videoPlayer.setTargetElementId(&amp;quot;video-player&amp;quot;);
    videoPlayer.setVideoData(playerVars);
    videoPlayer.initialize(startTime, true, true);

    // js api dispatcher
    // Only works now for void fns
    // TODO: figure out how to do callbacks synchronously, and have arguments, probably with JSON

    playerElementId = &amp;quot;video-player&amp;quot;;
      handleResize = function() {
    var windowHeight = window.innerHeight;
    var adjustedHeight = windowHeight - _gel('watch-longform-ad').offsetHeight;
    var percentHeight = Math.round((adjustedHeight * 100) / windowHeight) + &amp;quot;%&amp;quot;;
    _gel('video-player').style.height = percentHeight;
  }
  yt.events.listen(window, 'resize', handleResize);
  yt.events.listen(_gel('watch-longform-ad-placeholder'), 'resize', handleResize);

  }

  var availableFormats = yt.player.VideoFormat.formatListFromMap(
      []);

  var supportsHtml5 = yt.player.VideoFormat.hasSupportedFormats(availableFormats);

  if (supportsHtml5) {
    writeHtml5Embed(availableFormats);
  } else {
    _gel('embed-holder').removeChild(_gel('video-player'));
    writeFlashEmbed();
  }

  var playerElement = document.getElementById(playerElementId);

  //add JS API for iframe
  var whitelistApiCalls = {
    'playVideo': true,
    'pauseVideo': true,
    'seekTo': true,
    'mute': true,
    'unMute': true};
  var receiveYtMessage = function(event) {
    var message = event.data || (event.J &amp;amp;&amp;amp; event.J.data);
    if (typeof(message) == 'string') {
      // Chrome can handle message data being a non-string
      // object, but Firefox can't; best to always use JSON
      message = goog.json.parse(message);
    }
    var fnName = message &amp;amp;&amp;amp; message['f'];
    var argList = (message &amp;amp;&amp;amp; message['a']) || [];
    if (whitelistApiCalls[fnName] &amp;amp;&amp;amp; playerElement[fnName]) {
      var fn = playerElement[fnName];
      var result;
      if (fn) {
        result = fn.apply(playerElement, argList);
      }
    }
    // TODO(libra): return result?

    // TODO: figure out how to do callbacks synchronously
    //event.source.postMessage(&amp;quot;1234.567&amp;quot;, event.origin);
  };
  yt.events.listen(window, 'message', receiveYtMessage);


  &amp;lt;/script&amp;gt;


&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Although the developer(s) looked to be having the same cross-domain communication issues that others have combatted before using anchors (see my &lt;a href="http://stufftohelpyouout.blogspot.com/2010/04/gotchas-for-cross-domain-portlets-via.html"&gt;previous post&lt;/a&gt;- at least I think that is what those comments are about- I've not looked carefully), it is great that there is a neat solution in code for resizing the content within the iFrame (to do full-screen).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4350563038010817707?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4350563038010817707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4350563038010817707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4350563038010817707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4350563038010817707'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/10/cross-domain-iframe-resizing-in-youtube.html' title='Resizing Cross-domain Content in an iFrame in YouTube Video Embeds'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3866598042169708448</id><published>2010-10-20T14:31:00.006-04:00</published><updated>2010-10-20T14:41:52.810-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring root portlet servlet context beans'/><title type='text'>Spring Root, Portlet, and Servlet Contexts</title><content type='html'>&lt;em&gt;Note: the following pertains to spring-webmvc-portlet in Spring 2.5.6 with JSR-168 compliant portlets. It may be different in other versions.&lt;/em&gt;
&lt;p/&gt;
web.xml defines how the root application context (an instance of XmlWebApplicationContext) should look for configuration to setup beans in its context. If you define one or more files in contextConfigLocation, it loads those to define the beans, etc. for the root application context, to be available for the entire webapp. If singleton scope (the default for beans), they will be instantiated and configured on webapp load.
&lt;p/&gt;
For example, web.xml in the Jasig calendar portlet:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/web.xml"&gt;/WEB-INF/web.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
defines the following as config files to use for the root application context via contextConfigLocation:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/context/applicationContext.xml"&gt;/WEB-INF/context/applicationContext.xml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/context/calendarContext.xml"&gt;/WEB-INF/context/calendarContext.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
portlet.xml defines how the portlet application context (an instance of XmlPortletApplicationContext) should look for configuration to setup beans in its context. If you define one or more files in contextConfigLocation, it loads those to define the beans, etc. for portlet application context, to be available for the entire webapp. If singleton scope (the default for beans), they will be instantiated and configured on portlet load, which does not happen until the first time the portlet is loaded (the first request to a page that contains that portlet).
&lt;p/&gt;
For example, portlet.xml in the calendar portlet:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/portlet.xml"&gt;/WEB-INF/portlet.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
defines the following as config files to use for the portlet application context via contextConfigLocation:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/context/portlet/calendar.xml"&gt;/WEB-INF/context/portlet/calendar.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
web.xml also can define one or more additional servlets (e.g. for Ajax functionality). If the servlet-class is org.springframework.web.servlet.DispatcherServlet, it will look for (servlet-name)-servlet.xml as the spring config file that defines the beans for the servlet application context. I don't know for sure, but I'm guessing if singleton scope (the default for beans), they will be instantiated and configured on portlet load, which does not happen until the first time the portlet is loaded (the first request to a page that contains that portlet), unless the servlet is configured to load-on-startup in web.xml.
&lt;p/&gt;
For example, web.xml in the calendar portlet:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/web.xml"&gt;/WEB-INF/web.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
defines a servlet with servlet-name "spring" as a org.springframework.web.servlet.DispatcherServlet with load-on-startup, so it will load (servlet-name)-servlet.xml which is spring-servlet.xml:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://source.jasig.org/portlets/CalendarPortlet/tags/rel-1.0.0-M3/src/main/webapp/WEB-INF/spring-servlet.xml"&gt;/WEB-INF/spring-servlet.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
Defining the same context files both in web.xml and portlet.xml is usually wrong, because it basically means you are creating instances of beans in the root *and* portlet contexts. The portlet would always use the ones in the portlet contexts, so the root ones would be wasted, along with any resources they consumed.
&lt;p/&gt;
&lt;em&gt;Thanks to Eric Dalquist for pointing me in the right direction for this!&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3866598042169708448?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3866598042169708448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3866598042169708448' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3866598042169708448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3866598042169708448'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/10/spring-root-portlet-and-servlet.html' title='Spring Root, Portlet, and Servlet Contexts'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3256465236137231013</id><published>2010-10-06T19:24:00.003-04:00</published><updated>2010-10-11T16:29:00.542-04:00</updated><title type='text'>Nerot - Flexible Java Scheduling and Caching</title><content type='html'>Just did the initial import of &lt;a href="http://github.com/garysweaver/nerot"&gt;Nerot&lt;/a&gt; to Github. If you're looking for a fast and flexible Java scheduling library that is easily extensible and that has built-in support for RSS retrieval, calling any method (static or instance) on any Java object, in-memory caching, then check it out!
&lt;p/&gt;
It's primary immediate purpose for me to make keeping RSS feeds up-to-date (which it grabs via Rome) without even having to wait on retrieval possible. This is done by scheduling (via Quartz, Spring, and dynamic Spring bean creation) update of the feed and &lt;em&gt;always&lt;/em&gt; retrieving the feed that is cached in-memory and never making the client wait when they attempt to get the feed.
&lt;p/&gt;
This also means that it is an unreliable caching mechanism, i.e. if it has not been retrieved before in-memory, then it won't be there when you ask for it.
&lt;p/&gt;
At first this might seem to have limited application, but, if you think about it, most of the time an almost immediate response is better than waiting for a response because the cache expired, so why should the cache ever expire? So, it doesn't, and you never have to wait for a refresh since it is done in the background.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3256465236137231013?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3256465236137231013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3256465236137231013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3256465236137231013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3256465236137231013'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/10/nerot-flexible-java-scheduling-and.html' title='Nerot - Flexible Java Scheduling and Caching'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3672112817306242213</id><published>2010-09-28T15:47:00.000-04:00</published><updated>2010-09-28T15:47:17.664-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rails migration ORA-04043 oracle error'/><title type='text'>Workaround for "ORA-04043: object * does not exist" in rake db:migrate</title><content type='html'>This has happened at least twice now, so I thought I'd share a workaround.
&lt;p/&gt;
If you do a production migration in Rails:
&lt;pre&gt;&lt;code&gt;
RAILS_ENV=production rake db:migrate
&lt;/code&gt;&lt;/pre&gt;
and it dies with:
&lt;pre&gt;&lt;code&gt;
(in /path/to/some/project)
rake aborted!
ORA-04043: object plural_name_of_a_model does not exist
/path/to/some/project/Rakefile:10
(See full trace by running task with --trace) 
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then, first try using the --trace option:
&lt;pre&gt;&lt;code&gt;
RAILS_ENV=production rake db:migrate --trace
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
If the error is coming from a controller, move that controller and any others that fail to the base project directory (or somewhere outside of where it is supposed to be) and then run the migration again.
&lt;p/&gt;
Be sure to move the controllers back afterwards.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3672112817306242213?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3672112817306242213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3672112817306242213' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3672112817306242213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3672112817306242213'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/workaround-for-ora-04043-object-does.html' title='Workaround for &quot;ORA-04043: object * does not exist&quot; in rake db:migrate'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8725677880293786569</id><published>2010-09-23T15:25:00.005-04:00</published><updated>2010-10-20T14:49:11.236-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='goat-time'/><title type='text'>Goat-time</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_dkSPoUrJq0E/TJupX11FEJI/AAAAAAAAC38/ymfriQTdLZo/s1600/goat-time.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_dkSPoUrJq0E/TJupX11FEJI/AAAAAAAAC38/ymfriQTdLZo/s320/goat-time.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Text:&lt;br/&gt;
&lt;blockquote&gt;
松本武    &lt;br/&gt;
View profile   Translate to Translated (View Original)&lt;br/&gt;
 (4 users)  More options Sep 21, 3:02 pm&lt;br/&gt;
From: 松本武 &lt;takematu1...@gmail.com&gt;&lt;br/&gt;
Date: Tue, 21 Sep 2010 15:02:24 -0400&lt;br/&gt;
Local: Tues, Sep 21 2010 3:02 pm&lt;br/&gt;
Subject: [Shib-Users] goat-time with wind, pole, dragon inter help?&lt;br/&gt;
Forward | Print | Individual message | Show original | Report this message | Find messages by this author&lt;br/&gt;
This is question, engish is faulty therefore the right excused is
requested.  Thank google to translate to help.  SORRY!!!!!&lt;br/&gt;
&lt;br/&gt;
At often, the goat-time install a error is vomit.   To how many times like
the wind, a pole, and the dragon?   Install 2,3 repeat, spank, vomit blows&lt;br/&gt;
&lt;br/&gt;
14:14:01.869 - INFO&lt;br/&gt;
[edu.internet2.middleware.shibboleth.common.config.profile.JSPErrorHandlerBeanDefinitionParser:45]&lt;br/&gt;
- Parsing configuration for JSP error handler.&lt;br/&gt;
&lt;br/&gt;
Not precise the vomit but with aspect similar, is vomited concealed in fold of
goat-time lumber?   goat-time see like the wind, pole, and dragon?  This
insult to father's stones?    JSP error handler with wind, pole, dragon with
intercourse to goat-time?  Or chance lack of skill with a goat-time?&lt;br/&gt;
&lt;br/&gt;
Please apologize for your stupidity.  There are a many thank you 
&lt;/blockquote&gt;
&lt;p/&gt;
&lt;a href="http://groups.google.com/group/shibboleth-users/browse_thread/thread/123bd2d82822a3a7?pli=1"&gt;Original post here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8725677880293786569?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8725677880293786569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8725677880293786569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8725677880293786569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8725677880293786569'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/goat-time.html' title='Goat-time'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_dkSPoUrJq0E/TJupX11FEJI/AAAAAAAAC38/ymfriQTdLZo/s72-c/goat-time.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7290117478736374895</id><published>2010-09-17T11:42:00.008-04:00</published><updated>2010-09-17T12:56:05.809-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java base64 peoplecode peoplesoft apache commons codec'/><title type='text'>Modified Standalone Apache Commons Codec Base64 for Use in PeopleCode</title><content type='html'>Just modified Apache Commons Codec 1.4's Base64 class to be in the default package and made mods to remove all other codec dependencies and use IOException vs. EncoderException/DecoderException, and most importantly to remove interface usage and not have to implement encode(Object) and decode(Object) (required by the interface). The encode(Object) and decode(Object) overloads were messing things up when called from PeopleCode (in PeopleSoft PeopleTools v8.49.xx), I'm told.
&lt;p/&gt;
Here is the class to save in Base64.java and then compile in the required version of Java (1.4+, I think, but I compiled in 1.5):
&lt;pre&gt;&lt;code&gt;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the &amp;quot;License&amp;quot;); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;


/**
 * Provides Base64 encoding and decoding as defined by RFC 2045.
 * 
 * &amp;lt;p&amp;gt;
 * This class implements section &amp;lt;cite&amp;gt;6.8. Base64 Content-Transfer-Encoding&amp;lt;/cite&amp;gt; from RFC 2045 &amp;lt;cite&amp;gt;Multipurpose
 * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies&amp;lt;/cite&amp;gt; by Freed and Borenstein.
 * &amp;lt;/p&amp;gt;
 * &amp;lt;p&amp;gt;
 * The class can be parameterized in the following manner with various constructors:
 * &amp;lt;ul&amp;gt;
 * &amp;lt;li&amp;gt;URL-safe mode: Default off.&amp;lt;/li&amp;gt;
 * &amp;lt;li&amp;gt;Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
 * 4 in the encoded data.
 * &amp;lt;li&amp;gt;Line separator: Default is CRLF (&amp;quot;\r\n&amp;quot;)&amp;lt;/li&amp;gt;
 * &amp;lt;/ul&amp;gt;
 * &amp;lt;/p&amp;gt;
 * &amp;lt;p&amp;gt;
 * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
 * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
 * &amp;lt;/p&amp;gt;
 * Modified version of Base64 from Apache Commons Codec 1.4, by Gary S. Weaver, for use in PeopleCode that was needed at Duke University.
 *
 * Following changes were made:
 * &amp;lt;ul&amp;gt;
 * &amp;lt;li&amp;gt;Per internal request, was made standalone class and in default package.&amp;lt;/li&amp;gt;
 * &amp;lt;li&amp;gt;Integrated parts of org.apache.commons.codec.StringUtils and org.apache.commons.codec.CharEncoding so it could be a single class.&amp;lt;/li&amp;gt;
 * &amp;lt;li&amp;gt;Removed implementation of org.apache.commons.codec.BinaryDecoder/org.apache.commons.codec.BinaryEncoder interfaces and DecoderException/EncoderException classes,
 *     changing to use more general IOException to keep required code to a single class.&amp;lt;/li&amp;gt;
 * &amp;lt;li&amp;gt;Removed decode(Object) and encode(Object) methods that were causing the following error in PeopleSoft:
 *     Calling Java %1.%2: more than one overload matches. (...)
 *     While calling the noted Java method, the PeopleCode interface found more than once method signature 
 *     that could match the given parameter types.&amp;lt;/li&amp;gt;
 * &amp;lt;li&amp;gt;Removed javadoc info about revision, etc. so people wouldn't get confused and contact the wrong person about issues.&amp;lt;/li&amp;gt;
 * &amp;lt;/ul&amp;gt;
 */
public class Base64 {
    private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    /**
     * Chunk size per RFC 2045 section 6.8.
     * 
     * &amp;lt;p&amp;gt;
     * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
     * equal signs.
     * &amp;lt;/p&amp;gt;
     * 
     * @see &amp;lt;a href=&amp;quot;http://www.ietf.org/rfc/rfc2045.txt&amp;quot;&amp;gt;RFC 2045 section 6.8&amp;lt;/a&amp;gt;
     */
    static final int CHUNK_SIZE = 76;

    /**
     * Chunk separator per RFC 2045 section 2.1.
     *
     * &amp;lt;p&amp;gt;
     * N.B. The next major release may break compatibility and make this field private.
     * &amp;lt;/p&amp;gt;
     * 
     * @see &amp;lt;a href=&amp;quot;http://www.ietf.org/rfc/rfc2045.txt&amp;quot;&amp;gt;RFC 2045 section 2.1&amp;lt;/a&amp;gt;
     */
    static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};

    /**
     * This array is a lookup table that translates 6-bit positive integer index values into their &amp;quot;Base64 Alphabet&amp;quot;
     * equivalents as specified in Table 1 of RFC 2045.
     * 
     * Thanks to &amp;quot;commons&amp;quot; project in ws.apache.org for this code.
     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
     */
    private static final byte[] STANDARD_ENCODE_TABLE = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    };

    /**
     * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
     * changed to - and _ to make the encoded Base64 results more URL-SAFE.
     * This table is only used when the Base64's mode is set to URL-SAFE.
     */    
    private static final byte[] URL_SAFE_ENCODE_TABLE = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
    };

    /**
     * Byte used to pad output.
     */
    private static final byte PAD = '=';

    /**
     * This array is a lookup table that translates Unicode characters drawn from the &amp;quot;Base64 Alphabet&amp;quot; (as specified in
     * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
     * alphabet but fall within the bounds of the array are translated to -1.
     * 
     * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
     * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
     * 
     * Thanks to &amp;quot;commons&amp;quot; project in ws.apache.org for this code.
     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
     */
    private static final byte[] DECODE_TABLE = {
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
            55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
            5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
            24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
            35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
    };

    /** Mask used to extract 6 bits, used when encoding */
    private static final int MASK_6BITS = 0x3f;

    /** Mask used to extract 8 bits, used in decoding base64 bytes */
    private static final int MASK_8BITS = 0xff;

    // The static final fields above are used for the original static byte[] methods on Base64.
    // The private member fields below are used with the new streaming approach, which requires
    // some state be preserved between calls of encode() and decode().

    /**
     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
     * between the two modes.
     */
    private final byte[] encodeTable;

    /**
     * Line length for encoding. Not used when decoding. A value of zero or less implies no chunking of the base64
     * encoded data.
     */
    private final int lineLength;

    /**
     * Line separator for encoding. Not used when decoding. Only used if lineLength &amp;gt; 0.
     */
    private final byte[] lineSeparator;

    /**
     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
     * &amp;lt;code&amp;gt;decodeSize = 3 + lineSeparator.length;&amp;lt;/code&amp;gt;
     */
    private final int decodeSize;

    /**
     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
     * &amp;lt;code&amp;gt;encodeSize = 4 + lineSeparator.length;&amp;lt;/code&amp;gt;
     */
    private final int encodeSize;

    /**
     * Buffer for streaming.
     */
    private byte[] buffer;

    /**
     * Position where next character should be written in the buffer.
     */
    private int pos;

    /**
     * Position where next character should be read from the buffer.
     */
    private int readPos;

    /**
     * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
     * make sure each encoded line never goes beyond lineLength (if lineLength &amp;gt; 0).
     */
    private int currentLinePos;

    /**
     * Writes to the buffer only occur after every 3 reads when encoding, an every 4 reads when decoding. This variable
     * helps track that.
     */
    private int modulus;

    /**
     * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this Base64 object becomes useless,
     * and must be thrown away.
     */
    private boolean eof;

    /**
     * Place holder for the 3 bytes we're dealing with for our base64 logic. Bitwise operations store and extract the
     * base64 encoding or decoding from this variable.
     */
    private int x;

    /**
     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
     * &amp;lt;p&amp;gt;
     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
     * &amp;lt;/p&amp;gt;
     * 
     * &amp;lt;p&amp;gt;
     * When decoding all variants are supported.
     * &amp;lt;/p&amp;gt;
     */
    public Base64() {
        this(false);
    }

    /**
     * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
     * &amp;lt;p&amp;gt;
     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
     * &amp;lt;/p&amp;gt;
     * 
     * &amp;lt;p&amp;gt;
     * When decoding all variants are supported.
     * &amp;lt;/p&amp;gt;
     * 
     * @param urlSafe
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, URL-safe encoding is used. In most cases this should be set to
     *            &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;.
     * @since 1.4
     */
    public Base64(boolean urlSafe) {
        this(CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
    }

    /**
     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
     * &amp;lt;p&amp;gt;
     * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
     * STANDARD_ENCODE_TABLE.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * When decoding all variants are supported.
     * &amp;lt;/p&amp;gt;
     * 
     * @param lineLength
     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
     *            If lineLength &amp;lt;= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
     * @since 1.4
     */
    public Base64(int lineLength) {
        this(lineLength, CHUNK_SEPARATOR);
    }

    /**
     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
     * &amp;lt;p&amp;gt;
     * When encoding the line length and line separator are given in the constructor, and the encoding table is
     * STANDARD_ENCODE_TABLE.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * When decoding all variants are supported.
     * &amp;lt;/p&amp;gt;
     * 
     * @param lineLength
     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
     *            If lineLength &amp;lt;= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
     * @param lineSeparator
     *            Each line of encoded data will end with this sequence of bytes.
     * @throws IllegalArgumentException
     *             Thrown when the provided lineSeparator included some base64 characters.
     * @since 1.4
     */
    public Base64(int lineLength, byte[] lineSeparator) {
        this(lineLength, lineSeparator, false);
    }

    /**
     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
     * &amp;lt;p&amp;gt;
     * When encoding the line length and line separator are given in the constructor, and the encoding table is
     * STANDARD_ENCODE_TABLE.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * When decoding all variants are supported.
     * &amp;lt;/p&amp;gt;
     * 
     * @param lineLength
     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
     *            If lineLength &amp;lt;= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
     * @param lineSeparator
     *            Each line of encoded data will end with this sequence of bytes.
     * @param urlSafe
     *            Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
     *            operations. Decoding seamlessly handles both modes.
     * @throws IllegalArgumentException
     *             The provided lineSeparator included some base64 characters. That's not going to work!
     * @since 1.4
     */
    public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {
        if (lineSeparator == null) {
            lineLength = 0;  // disable chunk-separating
            lineSeparator = CHUNK_SEPARATOR;  // this just gets ignored
        }
        this.lineLength = lineLength &amp;gt; 0 ? (lineLength / 4) * 4 : 0;
        this.lineSeparator = new byte[lineSeparator.length];
        System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
        if (lineLength &amp;gt; 0) {
            this.encodeSize = 4 + lineSeparator.length;
        } else {
            this.encodeSize = 4;
        }
        this.decodeSize = this.encodeSize - 1;
        if (containsBase64Byte(lineSeparator)) {
            String sep = Base64.newStringUtf8(lineSeparator);
            throw new IllegalArgumentException(&amp;quot;lineSeperator must not contain base64 characters: [&amp;quot; + sep + &amp;quot;]&amp;quot;);
        }
        this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
    }

    /**
     * Returns our current encode mode. True if we're URL-SAFE, false otherwise.
     * 
     * @return true if we're in URL-SAFE mode, false otherwise.
     * @since 1.4
     */
    public boolean isUrlSafe() {
        return this.encodeTable == URL_SAFE_ENCODE_TABLE;
    }

    /**
     * Returns true if this Base64 object has buffered data for reading.
     * 
     * @return true if there is Base64 object still available for reading.
     */
    boolean hasData() {
        return this.buffer != null;
    }

    /**
     * Returns the amount of buffered data available for reading.
     * 
     * @return The amount of buffered data available for reading.
     */
    int avail() {
        return buffer != null ? pos - readPos : 0;
    }

    /** Doubles our buffer. */
    private void resizeBuffer() {
        if (buffer == null) {
            buffer = new byte[DEFAULT_BUFFER_SIZE];
            pos = 0;
            readPos = 0;
        } else {
            byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
            System.arraycopy(buffer, 0, b, 0, buffer.length);
            buffer = b;
        }
    }

    /**
     * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
     * bytes. Returns how many bytes were actually extracted.
     * 
     * @param b
     *            byte[] array to extract the buffered data into.
     * @param bPos
     *            position in byte[] array to start extraction at.
     * @param bAvail
     *            amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
     * @return The number of bytes successfully extracted into the provided byte[] array.
     */
    int readResults(byte[] b, int bPos, int bAvail) {
        if (buffer != null) {
            int len = Math.min(avail(), bAvail);
            if (buffer != b) {
                System.arraycopy(buffer, readPos, b, bPos, len);
                readPos += len;
                if (readPos &amp;gt;= pos) {
                    buffer = null;
                }
            } else {
                // Re-using the original consumer's output array is only
                // allowed for one round.
                buffer = null;
            }
            return len;
        }
        return eof ? -1 : 0;
    }

    /**
     * Sets the streaming buffer. This is a small optimization where we try to buffer directly to the consumer's output
     * array for one round (if the consumer calls this method first) instead of starting our own buffer.
     * 
     * @param out
     *            byte[] array to buffer directly to.
     * @param outPos
     *            Position to start buffering into.
     * @param outAvail
     *            Amount of bytes available for direct buffering.
     */
    void setInitialBuffer(byte[] out, int outPos, int outAvail) {
        // We can re-use consumer's original output array under
        // special circumstances, saving on some System.arraycopy().
        if (out != null &amp;amp;&amp;amp; out.length == outAvail) {
            buffer = out;
            pos = outPos;
            readPos = outPos;
        }
    }

    /**
     * &amp;lt;p&amp;gt;
     * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
     * the data to encode, and once with inAvail set to &amp;quot;-1&amp;quot; to alert encoder that EOF has been reached, so flush last
     * remaining bytes (if not multiple of 3).
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Thanks to &amp;quot;commons&amp;quot; project in ws.apache.org for the bitwise operations, and general approach.
     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
     * &amp;lt;/p&amp;gt;
     * 
     * @param in
     *            byte[] array of binary data to base64 encode.
     * @param inPos
     *            Position to start reading data from.
     * @param inAvail
     *            Amount of bytes available from input for encoding.
     */
    void encode(byte[] in, int inPos, int inAvail) {
        if (eof) {
            return;
        }
        // inAvail &amp;lt; 0 is how we're informed of EOF in the underlying data we're
        // encoding.
        if (inAvail &amp;lt; 0) {
            eof = true;
            if (buffer == null || buffer.length - pos &amp;lt; encodeSize) {
                resizeBuffer();
            }
            switch (modulus) {
                case 1 :
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 2) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[(x &amp;lt;&amp;lt; 4) &amp;amp; MASK_6BITS];
                    // URL-SAFE skips the padding to further reduce size.
                    if (encodeTable == STANDARD_ENCODE_TABLE) {
                        buffer[pos++] = PAD;
                        buffer[pos++] = PAD;
                    }
                    break;

                case 2 :
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 10) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 4) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[(x &amp;lt;&amp;lt; 2) &amp;amp; MASK_6BITS];
                    // URL-SAFE skips the padding to further reduce size.
                    if (encodeTable == STANDARD_ENCODE_TABLE) {
                        buffer[pos++] = PAD;
                    }
                    break;
            }
            if (lineLength &amp;gt; 0 &amp;amp;&amp;amp; pos &amp;gt; 0) {
                System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
                pos += lineSeparator.length;
            }
        } else {
            for (int i = 0; i &amp;lt; inAvail; i++) {
                if (buffer == null || buffer.length - pos &amp;lt; encodeSize) {
                    resizeBuffer();
                }
                modulus = (++modulus) % 3;
                int b = in[inPos++];
                if (b &amp;lt; 0) {
                    b += 256;
                }
                x = (x &amp;lt;&amp;lt; 8) + b;
                if (0 == modulus) {
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 18) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 12) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[(x &amp;gt;&amp;gt; 6) &amp;amp; MASK_6BITS];
                    buffer[pos++] = encodeTable[x &amp;amp; MASK_6BITS];
                    currentLinePos += 4;
                    if (lineLength &amp;gt; 0 &amp;amp;&amp;amp; lineLength &amp;lt;= currentLinePos) {
                        System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
                        pos += lineSeparator.length;
                        currentLinePos = 0;
                    }
                }
            }
        }
    }

    /**
     * &amp;lt;p&amp;gt;
     * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
     * with the data to decode, and once with inAvail set to &amp;quot;-1&amp;quot; to alert decoder that EOF has been reached. The &amp;quot;-1&amp;quot;
     * call is not necessary when decoding, but it doesn't hurt, either.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
     * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
     * garbage-out philosophy: it will not check the provided data for validity.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Thanks to &amp;quot;commons&amp;quot; project in ws.apache.org for the bitwise operations, and general approach.
     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
     * &amp;lt;/p&amp;gt;
     * 
     * @param in
     *            byte[] array of ascii data to base64 decode.
     * @param inPos
     *            Position to start reading data from.
     * @param inAvail
     *            Amount of bytes available from input for encoding.
     */
    void decode(byte[] in, int inPos, int inAvail) {
        if (eof) {
            return;
        }
        if (inAvail &amp;lt; 0) {
            eof = true;
        }
        for (int i = 0; i &amp;lt; inAvail; i++) {
            if (buffer == null || buffer.length - pos &amp;lt; decodeSize) {
                resizeBuffer();
            }
            byte b = in[inPos++];
            if (b == PAD) {
                // We're done.
                eof = true;
                break;
            } else {
                if (b &amp;gt;= 0 &amp;amp;&amp;amp; b &amp;lt; DECODE_TABLE.length) {
                    int result = DECODE_TABLE[b];
                    if (result &amp;gt;= 0) {
                        modulus = (++modulus) % 4;
                        x = (x &amp;lt;&amp;lt; 6) + result;
                        if (modulus == 0) {
                            buffer[pos++] = (byte) ((x &amp;gt;&amp;gt; 16) &amp;amp; MASK_8BITS);
                            buffer[pos++] = (byte) ((x &amp;gt;&amp;gt; 8) &amp;amp; MASK_8BITS);
                            buffer[pos++] = (byte) (x &amp;amp; MASK_8BITS);
                        }
                    }
                }
            }
        }

        // Two forms of EOF as far as base64 decoder is concerned: actual
        // EOF (-1) and first time '=' character is encountered in stream.
        // This approach makes the '=' padding characters completely optional.
        if (eof &amp;amp;&amp;amp; modulus != 0) {
            x = x &amp;lt;&amp;lt; 6;
            switch (modulus) {
                case 2 :
                    x = x &amp;lt;&amp;lt; 6;
                    buffer[pos++] = (byte) ((x &amp;gt;&amp;gt; 16) &amp;amp; MASK_8BITS);
                    break;
                case 3 :
                    buffer[pos++] = (byte) ((x &amp;gt;&amp;gt; 16) &amp;amp; MASK_8BITS);
                    buffer[pos++] = (byte) ((x &amp;gt;&amp;gt; 8) &amp;amp; MASK_8BITS);
                    break;
            }
        }
    }

    /**
     * Returns whether or not the &amp;lt;code&amp;gt;octet&amp;lt;/code&amp;gt; is in the base 64 alphabet.
     * 
     * @param octet
     *            The value to test
     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the value is defined in the the base 64 alphabet, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; otherwise.
     * @since 1.4
     */
    public static boolean isBase64(byte octet) {
        return octet == PAD || (octet &amp;gt;= 0 &amp;amp;&amp;amp; octet &amp;lt; DECODE_TABLE.length &amp;amp;&amp;amp; DECODE_TABLE[octet] != -1);
    }

    /**
     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
     * method treats whitespace as valid.
     * 
     * @param arrayOctet
     *            byte array to test
     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
     *         false, otherwise
     */
    public static boolean isArrayByteBase64(byte[] arrayOctet) {
        for (int i = 0; i &amp;lt; arrayOctet.length; i++) {
            if (!isBase64(arrayOctet[i]) &amp;amp;&amp;amp; !isWhiteSpace(arrayOctet[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
     * 
     * @param arrayOctet
     *            byte array to test
     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if any byte is a valid character in the Base64 alphabet; false herwise
     */
    private static boolean containsBase64Byte(byte[] arrayOctet) {
        for (int i = 0; i &amp;lt; arrayOctet.length; i++) {
            if (isBase64(arrayOctet[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Encodes binary data using the base64 algorithm but does not chunk the output.
     * 
     * @param binaryData
     *            binary data to encode
     * @return byte[] containing Base64 characters in their UTF-8 representation.
     */
    public static byte[] encodeBase64(byte[] binaryData) {
        return encodeBase64(binaryData, false);
    }

    /**
     * Encodes binary data using the base64 algorithm into 76 character blocks separated by CRLF.
     *
     * @param binaryData
     *            binary data to encode
     * @return String containing Base64 characters.
     * @since 1.4
     */    
    public static String encodeBase64String(byte[] binaryData) {
        return Base64.newStringUtf8(encodeBase64(binaryData, true));
    }
    
    /**
     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
     * url-safe variation emits - and _ instead of + and / characters.
     * 
     * @param binaryData
     *            binary data to encode
     * @return byte[] containing Base64 characters in their UTF-8 representation.
     * @since 1.4
     */
    public static byte[] encodeBase64URLSafe(byte[] binaryData) {
        return encodeBase64(binaryData, false, true);
    }

    /**
     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
     * url-safe variation emits - and _ instead of + and / characters.
     *
     * @param binaryData
     *            binary data to encode
     * @return String containing Base64 characters
     * @since 1.4
     */    
    public static String encodeBase64URLSafeString(byte[] binaryData) {
        return Base64.newStringUtf8(encodeBase64(binaryData, false, true));
    }    

    /**
     * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
     * 
     * @param binaryData
     *            binary data to encode
     * @return Base64 characters chunked in 76 character blocks
     */
    public static byte[] encodeBase64Chunked(byte[] binaryData) {
        return encodeBase64(binaryData, true);
    }

    /**
     * Decodes a String containing containing characters in the Base64 alphabet.
     *
     * @param pArray
     *            A String containing Base64 character data
     * @return a byte array containing binary data
     * @since 1.4
     */
    public byte[] decode(String pArray) {
        return decode(Base64.getBytesUtf8(pArray));
    }

    /**
     * Decodes a byte[] containing containing characters in the Base64 alphabet.
     * 
     * @param pArray
     *            A byte array containing Base64 character data
     * @return a byte array containing binary data
     */
    public byte[] decode(byte[] pArray) {
        reset();
        if (pArray == null || pArray.length == 0) {
            return pArray;
        }
        long len = (pArray.length * 3) / 4;
        byte[] buf = new byte[(int) len];
        setInitialBuffer(buf, 0, buf.length);
        decode(pArray, 0, pArray.length);
        decode(pArray, 0, -1); // Notify decoder of EOF.

        // Would be nice to just return buf (like we sometimes do in the encode
        // logic), but we have no idea what the line-length was (could even be
        // variable).  So we cannot determine ahead of time exactly how big an
        // array is necessary.  Hence the need to construct a 2nd byte array to
        // hold the final result:

        byte[] result = new byte[pos];
        readResults(result, 0, result.length);
        return result;
    }

    /**
     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
     * 
     * @param binaryData
     *            Array containing binary data to encode.
     * @param isChunked
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; this encoder will chunk the base64 output into 76 character blocks
     * @return Base64-encoded data.
     * @throws IllegalArgumentException
     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
     */
    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
        return encodeBase64(binaryData, isChunked, false);
    }

    /**
     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
     * 
     * @param binaryData
     *            Array containing binary data to encode.
     * @param isChunked
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; this encoder will chunk the base64 output into 76 character blocks
     * @param urlSafe
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; this encoder will emit - and _ instead of the usual + and / characters.
     * @return Base64-encoded data.
     * @throws IllegalArgumentException
     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
     * @since 1.4
     */
    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) {
        return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
    }

    /**
     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
     * 
     * @param binaryData
     *            Array containing binary data to encode.
     * @param isChunked
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; this encoder will chunk the base64 output into 76 character blocks
     * @param urlSafe
     *            if &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; this encoder will emit - and _ instead of the usual + and / characters.
     * @param maxResultSize
     *            The maximum result size to accept.
     * @return Base64-encoded data.
     * @throws IllegalArgumentException
     *             Thrown when the input array needs an output array bigger than maxResultSize
     * @since 1.4
     */
    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
        if (binaryData == null || binaryData.length == 0) {
            return binaryData;
        }

        long len = getEncodeLength(binaryData, CHUNK_SIZE, CHUNK_SEPARATOR);
        if (len &amp;gt; maxResultSize) {
            throw new IllegalArgumentException(&amp;quot;Input array too big, the output array would be bigger (&amp;quot; +
                len +
                &amp;quot;) than the specified maxium size of &amp;quot; +
                maxResultSize);
        }
                
        Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
        return b64.encode(binaryData);
    }

    /**
     * Decodes a Base64 String into octets
     *
     * @param base64String
     *            String containing Base64 data
     * @return Array containing decoded data.
     * @since 1.4
     */
    public static byte[] decodeBase64(String base64String) {
        return new Base64().decode(base64String);
    }

    /**
     * Decodes Base64 data into octets
     * 
     * @param base64Data
     *            Byte array containing Base64 data
     * @return Array containing decoded data.
     */
    public static byte[] decodeBase64(byte[] base64Data) {
        return new Base64().decode(base64Data);
    }

    /**
     * Discards any whitespace from a base-64 encoded block.
     * 
     * @param data
     *            The base-64 encoded data to discard the whitespace from.
     * @return The data, less whitespace (see RFC 2045).
     * @deprecated This method is no longer needed
     */
    static byte[] discardWhitespace(byte[] data) {
        byte groomedData[] = new byte[data.length];
        int bytesCopied = 0;
        for (int i = 0; i &amp;lt; data.length; i++) {
            switch (data[i]) {
                case ' ' :
                case '\n' :
                case '\r' :
                case '\t' :
                    break;
                default :
                    groomedData[bytesCopied++] = data[i];
            }
        }
        byte packedData[] = new byte[bytesCopied];
        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
        return packedData;
    }

    /**
     * Checks if a byte value is whitespace or not.
     * 
     * @param byteToCheck
     *            the byte to check
     * @return true if byte is whitespace, false otherwise
     */
    private static boolean isWhiteSpace(byte byteToCheck) {
        switch (byteToCheck) {
            case ' ' :
            case '\n' :
            case '\r' :
            case '\t' :
                return true;
            default :
                return false;
        }
    }

    /**
     * Encodes a byte[] containing binary data, into a String containing characters in the Base64 alphabet.
     *
     * @param pArray
     *            a byte array containing binary data
     * @return A String containing only Base64 character data
     * @since 1.4
     */    
    public String encodeToString(byte[] pArray) {
        return Base64.newStringUtf8(encode(pArray));
    }

    /**
     * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet.
     * 
     * @param pArray
     *            a byte array containing binary data
     * @return A byte array containing only Base64 character data
     */
    public byte[] encode(byte[] pArray) {
        reset();        
        if (pArray == null || pArray.length == 0) {
            return pArray;
        }
        long len = getEncodeLength(pArray, lineLength, lineSeparator);
        byte[] buf = new byte[(int) len];
        setInitialBuffer(buf, 0, buf.length);
        encode(pArray, 0, pArray.length);
        encode(pArray, 0, -1); // Notify encoder of EOF.
        // Encoder might have resized, even though it was unnecessary.
        if (buffer != buf) {
            readResults(buf, 0, buf.length);
        }
        // In URL-SAFE mode we skip the padding characters, so sometimes our
        // final length is a bit smaller.
        if (isUrlSafe() &amp;amp;&amp;amp; pos &amp;lt; buf.length) {
            byte[] smallerBuf = new byte[pos];
            System.arraycopy(buf, 0, smallerBuf, 0, pos);
            buf = smallerBuf;
        }
        return buf;        
    }

    /**
     * Pre-calculates the amount of space needed to base64-encode the supplied array.
     *
     * @param pArray byte[] array which will later be encoded
     * @param chunkSize line-length of the output (&amp;lt;= 0 means no chunking) between each
     *        chunkSeparator (e.g. CRLF).
     * @param chunkSeparator the sequence of bytes used to separate chunks of output (e.g. CRLF).
     *
     * @return amount of space needed to encoded the supplied array.  Returns
     *         a long since a max-len array will require Integer.MAX_VALUE + 33%.
     */
    private static long getEncodeLength(byte[] pArray, int chunkSize, byte[] chunkSeparator) {
        // base64 always encodes to multiples of 4.
        chunkSize = (chunkSize / 4) * 4;

        long len = (pArray.length * 4) / 3;
        long mod = len % 4;
        if (mod != 0) {
            len += 4 - mod;
        }
        if (chunkSize &amp;gt; 0) {
            boolean lenChunksPerfectly = len % chunkSize == 0;
            len += (len / chunkSize) * chunkSeparator.length;
            if (!lenChunksPerfectly) {
                len += chunkSeparator.length;
            }
        }
        return len;
    }

    // Implementation of integer encoding used for crypto
    /**
     * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
     * 
     * @param pArray
     *            a byte array containing base64 character data
     * @return A BigInteger
     * @since 1.4
     */
    public static BigInteger decodeInteger(byte[] pArray) {
        return new BigInteger(1, decodeBase64(pArray));
    }

    /**
     * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
     * 
     * @param bigInt
     *            a BigInteger
     * @return A byte array containing base64 character data
     * @throws NullPointerException
     *             if null is passed in
     * @since 1.4
     */
    public static byte[] encodeInteger(BigInteger bigInt) {
        if (bigInt == null) {
            throw new NullPointerException(&amp;quot;encodeInteger called with null parameter&amp;quot;);
        }
        return encodeBase64(toIntegerBytes(bigInt), false);
    }

    /**
     * Returns a byte-array representation of a &amp;lt;code&amp;gt;BigInteger&amp;lt;/code&amp;gt; without sign bit.
     * 
     * @param bigInt
     *            &amp;lt;code&amp;gt;BigInteger&amp;lt;/code&amp;gt; to be converted
     * @return a byte array representation of the BigInteger parameter
     */
    static byte[] toIntegerBytes(BigInteger bigInt) {
        int bitlen = bigInt.bitLength();
        // round bitlen
        bitlen = ((bitlen + 7) &amp;gt;&amp;gt; 3) &amp;lt;&amp;lt; 3;
        byte[] bigBytes = bigInt.toByteArray();

        if (((bigInt.bitLength() % 8) != 0) &amp;amp;&amp;amp; (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
            return bigBytes;
        }
        // set up params for copying everything but sign bit
        int startSrc = 0;
        int len = bigBytes.length;

        // if bigInt is exactly byte-aligned, just skip signbit in copy
        if ((bigInt.bitLength() % 8) == 0) {
            startSrc = 1;
            len--;
        }
        int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
        byte[] resizedBytes = new byte[bitlen / 8];
        System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
        return resizedBytes;
    }

    /**
     * Resets this Base64 object to its initial newly constructed state.
     */
    private void reset() {
        buffer = null;
        pos = 0;
        readPos = 0;
        currentLinePos = 0;
        modulus = 0;
        eof = false;
    }

    
    // The following was moved here from org.apache.commons.codec.CharEncoding. Also modified to reference this class.
    
    /**
     * &amp;lt;p&amp;gt;
     * Eight-bit Unicode Transformation Format.
     * &amp;lt;/p&amp;gt;
     * &amp;lt;p&amp;gt;
     * Every implementation of the Java platform is required to support this character encoding.
     * &amp;lt;/p&amp;gt;
     * 
     * @see &amp;lt;a href=&amp;quot;http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html&amp;quot;&amp;gt;Standard charsets&amp;lt;/a&amp;gt;
     */
    public static final String UTF_8 = &amp;quot;UTF-8&amp;quot;;

    
    // The following was moved here from org.apache.commons.codec.StringUtils. Also modified to reference this class.

    /**
     * Constructs a new &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; by decoding the specified array of bytes using the UTF-8 charset.
     * 
     * @param bytes
     *            The bytes to be decoded into characters
     * @return A new &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; decoded from the specified array of bytes using the given charset.
     * @throws IllegalStateException
     *             Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
     *             charset is required.
     */
    public static String newStringUtf8(byte[] bytes) {
        return Base64.newString(bytes, Base64.UTF_8);
    }

    private static IllegalStateException newIllegalStateException(String charsetName, UnsupportedEncodingException e) {
        return new IllegalStateException(charsetName + &amp;quot;: &amp;quot; + e);
    }

    /**
     * Constructs a new &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; by decoding the specified array of bytes using the given charset.
     * &amp;lt;p&amp;gt;
     * This method catches {@link UnsupportedEncodingException} and re-throws it as {@link IllegalStateException}, which
     * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
     * &amp;lt;/p&amp;gt;
     * 
     * @param bytes
     *            The bytes to be decoded into characters
     * @param charsetName
     *            The name of a required {@link java.nio.charset.Charset}
     * @return A new &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; decoded from the specified array of bytes using the given charset.
     * @throws IllegalStateException
     *             Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
     *             required charset name.
     * @see CharEncoding
     * @see String#String(byte[], String)
     */
    public static String newString(byte[] bytes, String charsetName) {
        if (bytes == null) {
            return null;
        }
        try {
            return new String(bytes, charsetName);
        } catch (UnsupportedEncodingException e) {
            throw Base64.newIllegalStateException(charsetName, e);
        }
    }

    /**
     * Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte
     * array.
     * 
     * @param string
     *            the String to encode
     * @return encoded bytes
     * @throws IllegalStateException
     *             Thrown when the charset is missing, which should be never according the the Java specification.
     * @see &amp;lt;a href=&amp;quot;http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html&amp;quot;&amp;gt;Standard charsets&amp;lt;/a&amp;gt;
     * @see #getBytesUnchecked(String, String)
     */
    public static byte[] getBytesUtf8(String string) {
        return Base64.getBytesUnchecked(string, Base64.UTF_8);
    }

    /**
     * Encodes the given string into a sequence of bytes using the named charset, storing the result into a new byte
     * array.
     * &amp;lt;p&amp;gt;
     * This method catches {@link UnsupportedEncodingException} and rethrows it as {@link IllegalStateException}, which
     * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
     * &amp;lt;/p&amp;gt;
     * 
     * @param string
     *            the String to encode
     * @param charsetName
     *            The name of a required {@link java.nio.charset.Charset}
     * @return encoded bytes
     * @throws IllegalStateException
     *             Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
     *             required charset name.
     * @see CharEncoding
     * @see String#getBytes(String)
     */
    public static byte[] getBytesUnchecked(String string, String charsetName) {
        if (string == null) {
            return null;
        }
        try {
            return string.getBytes(charsetName);
        } catch (UnsupportedEncodingException e) {
            throw Base64.newIllegalStateException(charsetName, e);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
After compiling that Java file into Base64.class and putting Base64.class into the classes dir, here is an example for how it could be called in PeopleCode that I was provided:
&lt;pre&gt;&lt;code&gt;
Local object &amp;amp;oDecoder = CreateJavaObject(&amp;quot;Base64&amp;quot;);
Local object &amp;amp;dOut = &amp;amp;oDecoder.decode(&amp;amp;strAttachContent);
Local File &amp;amp;file;
&amp;amp;file = GetFile(&amp;amp;strDocFileName, &amp;quot;W&amp;quot;, &amp;quot;UTF8&amp;quot;);
Local string &amp;amp;strPutFileName = &amp;amp;file.Name;
&amp;amp;file.Close();
Local JavaObject &amp;amp;FOS = CreateJavaObject(&amp;quot;java.io.FileOutputStream&amp;quot;, &amp;amp;strPutFileName);
Local JavaObject &amp;amp;DOS = CreateJavaObject(&amp;quot;java.io.DataOutputStream&amp;quot;, &amp;amp;FOS);
&amp;amp;DOS.write(&amp;amp;dOut, 0, &amp;amp;dOut.length);
&amp;amp;DOS.close();
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Hope that helps someone else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7290117478736374895?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7290117478736374895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7290117478736374895' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7290117478736374895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7290117478736374895'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/modified-standalone-apache-commons.html' title='Modified Standalone Apache Commons Codec Base64 for Use in PeopleCode'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1191316308232015126</id><published>2010-09-13T16:40:00.005-04:00</published><updated>2010-09-13T16:51:17.332-04:00</updated><title type='text'>Summary of SQL Antipatterns Presentation</title><content type='html'>The following is a summary of the presentation, "SQL Antipatterns - Tables and Queries That Don't Work", by Bill Karwin. Please see Bill's presentation for details about each of these:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.scribd.com/doc/2670985/SQL-Antipatterns"&gt;http://www.scribd.com/doc/2670985/SQL-Antipatterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
Things not to do:
&lt;ul&gt;
&lt;li&gt;Comma-Separated Lists: Storing list of relations as a comma-delimited list of ids.&lt;/li&gt;
&lt;li&gt;Multi-Column Attributes: Storing ids to related tables as additional columns in same table (e.g. product_id1, product_id2, product_id3)&lt;/li&gt;
&lt;li&gt;Entity-Attribute-Value: Storing generic key/value data in a table (e.g. attr_name, attr_value) in cases where attributes do not have to be truly dynamic, constraints on data are not enforced by application, non-relational solutions have not been explored, etc.&lt;/li&gt;
&lt;li&gt;Metadata Tribbles: Putting year (data) into database table name or other similar splits for performance that ignore ability to partition horizontally, vertically, or use dependent tables.&lt;/li&gt;
&lt;li&gt;ID Required: Creating a new ID field (calling it "ID") and ignoring other ID fields that could be used as ID or composite ID or that could have more descriptive names.&lt;/li&gt;
&lt;li&gt;Phantom Files: Storing links in database to external files that should be managed transactionally, backed up, and restored with the database.&lt;/li&gt;
&lt;li&gt;FLOAT: Storing decimal numbers (especially money or time estimates) as inexact FLOAT data type vs. NUMERIC data type.&lt;/li&gt;
&lt;li&gt;ENUM: Using ENUM datatype when the values may change.&lt;/li&gt;
&lt;li&gt;Readable Passwords: Storing passwords in plain text (e.g. for purpose of providing to user upon request for password) rather than MD5 digest w/salt in application prior to storage in DB.&lt;/li&gt;
&lt;li&gt;Ambiguous GROUP BY: Using GROUP BY and select some attributes in result without using functionally dependent attributes, GROUP_CONCAT with attribute, or using OUTER JOIN instead.&lt;/li&gt;
&lt;li&gt;HAVING: Using HAVING clause vs. WHERE clause, not realizing order of execution for HAVING is after WHERE, SELECT, aliases, and GROUP BY (and only before ORDER BY). &lt;/li&gt;
&lt;li&gt;Poor Man's Search Engine: Using LIKE with wildcards on both sides or RLIKE (regexp) (Note: index is used if wildcard only at end of LIKE, but not used if wildcard at beginning) rather than MySQL FULLTEXT index (MyISAM only), Lucene, or Sphinx Search (for example).&lt;/li&gt;
&lt;li&gt;Implicit Columns: Selecting wildcard columns.&lt;/li&gt;
&lt;li&gt;User-supplied SQL: Letting users supply SQL.&lt;/li&gt;
&lt;li&gt;SQL Injection: Putting user-supplied data into SQL expression directly rather than filtering, parameterizing.&lt;/li&gt;
&lt;li&gt;Parameter Facade: Reusing parameter entered by user for list used by application, like WHERE bug_id in LIST ( $user_supplied_parameter ) because you want to have application also supply as "1234,3456,5678". (basically same as SQL injection)&lt;/li&gt;
&lt;li&gt;Pseudokey Neat Freak: Changing ID values to eliminate gaps between sequential IDs OR recycling ID values.&lt;/li&gt;
&lt;li&gt;Session Coupling: Using persistent connections and reusing uncommitted transactions, changing/using connections character set, using DB session variables, using LAST_INSERT_ID.&lt;/li&gt;
&lt;li&gt;Phantom Side Effects: Executing external effects (that don't obey ROLLBACK) in database triggers, stored procs, and functions, and kicking off application functionality (like emailing link with ID, etc.) without waiting on transactions to complete.&lt;/li&gt;
&lt;/ul&gt;
See also:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.pragprog.com/titles/bksqla/sql-antipatterns"&gt;SQL Antipatterns: Avoiding the Pitfalls of Database Programming by Bill Karwin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1191316308232015126?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1191316308232015126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1191316308232015126' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1191316308232015126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1191316308232015126'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/summary-of-sql-antipatterns.html' title='Summary of SQL Antipatterns Presentation'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5977059257277698893</id><published>2010-09-13T11:12:00.005-04:00</published><updated>2010-09-13T11:21:00.732-04:00</updated><title type='text'>Active Record and ORA-00932: inconsistent datatypes: expected - got CLOB</title><content type='html'>CLOBs can be problematic in Rails, and yet they are the default datatype for ActiveRecord text type (used for textareas) when used with Oracle. With the various named scopes, etc. you can use with ActiveRecord, even seemingly simple code like:
&lt;pre&gt;&lt;code&gt;
(@user.your_models &amp;&amp; @user.your_models.length &gt; 0)
&lt;/code&gt;&lt;/pre&gt;
with this code in YourModel:
&lt;pre&gt;&lt;code&gt;
  default_scope :conditions =&amp;gt; {:another_model_id =&amp;gt; AnotherModel.something.id, :deleted_at =&amp;gt; nil}
  belongs_to :another_model

  has_many :some_join_models  
  has_many :users, :through =&amp;gt; :some_join_models, :uniq =&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;
can cause errors like:
&lt;pre&gt;&lt;code&gt;
OCIError: ORA-00932: inconsistent datatypes: expected - got CLOB: SELECT DISTINCT your_models.* FROM your_models  INNER JOIN some_join_models ON your_models.id = some_join_models.your_model_id    WHERE ((some_join_models.user_id = 1234)) AND (your_models.deleted_at IS NULL AND your_models.another_model_id = 6789) 

RAILS_ROOT: ...
Application Trace | Framework Trace | Full Trace

.../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log'
.../vendor/gems/activerecord-oracle_enhanced-adapter-1.2.0/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:927:in `select'
.../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache'
.../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:60:in `select_all'
.../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:81:in `cache_sql'
.../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:60:in `select_all'
.../vendor/rails/activerecord/lib/active_record/base.rb:661:in `find_by_sql'
.../vendor/rails/activerecord/lib/active_record/base.rb:1553:in `find_every'
.../vendor/rails/activerecord/lib/active_record/base.rb:615:in `find'
.../vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb:73:in `find_target'
.../vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:349:in `load_target'
.../vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:283:in `length'
.../app/controllers/application_controller.rb:34:in `a_method_that_just_reference_all_models'
.../app/controllers/application_controller.rb:12:in `a_method'
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
So as a first thought, why not convert the CLOB to VARCHAR2? It's faster to access. But, since many CRUD UI and form helper tools assume that you are using text for textarea and string for text input, if you change a text type to a string type, you might have more complexity in displaying the textarea as you need it to for that field. If you want to convert to VARCHAR2 anyway, see &lt;a href="http://snippets.dzone.com/posts/show/3022"&gt;this snippet&lt;/a&gt;. However, you might instead look into how you can adjust things to specify references to the CLOB column as "DBMS_LOB.SUBSTR(name_of_column)". We used that previously to get sort_by in our CRUD tool working.
&lt;p/&gt;
The problem was the use of uniq =&amp;gt; true in all related models. It was there to try to keep additional associations from being displayed that were duplicate, but it wasn't even doing that correctly (probably because of the unique id on the association model, SomeJoinModel, making all association records unique).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5977059257277698893?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5977059257277698893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5977059257277698893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5977059257277698893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5977059257277698893'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/active-record-and-ora-00932.html' title='Active Record and ORA-00932: inconsistent datatypes: expected - got CLOB'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7511300352336111218</id><published>2010-09-10T13:54:00.015-04:00</published><updated>2010-09-13T11:07:24.700-04:00</updated><title type='text'>Ruby Script to Identify CLOBs and Required Length of VARCHAR2 for Conversion</title><content type='html'>All text type fields in Rails are stored in Oracle as CLOBs (at time of writing), so finding CLOB types may be as easy as looking in db/schema.rb and looking for text type fields. But what if you want to find the length of the largest value of those CLOBs, or are thinking about converting them to string types?
&lt;p/&gt;
The following script can be saved to loads/save_me_from_the_clob.rb and then loaded via script/console and load 'loads/save_me_from_the_clob.rb'. It will list all DB tables with CLOBs with the required length of VARCHAR2 based on the current maximum value/length of the CLOB column, so you wouldn't truncate any existing values if you converted them, in theory.
&lt;pre&gt;&lt;code&gt;
# avoid: ActiveRecord::StatementInvalid (OCIError: ORA-00932: inconsistent datatypes: expected - got CLOB
# by indentifying CLOB columns and their maximum values, which can be used to create a migration.

# Written by Gary S. Weaver 9/10/2010

class MaxLengthUtility &amp;lt; ActiveRecord::Base

  # remove the database table dependency
  def self.columns() @columns ||= []; end
  
  def self.find_max_length(table_name, column_name)
    sql = ''
    begin
      # Note: commented out version will cause errors with length &amp;gt; 3999, I think
      #sql = &amp;lt;&amp;lt;-SQL_END
      #SELECT * FROM (SELECT LENGTH(DBMS_LOB.SUBSTR(#{column_name})) AS &amp;quot;LENGTH&amp;quot; FROM #{table_name} WHERE LENGTH(DBMS_LOB.SUBSTR(#{column_name})) IS NOT NULL ORDER BY LENGTH(DBMS_LOB.SUBSTR(#{column_name})) DESC) WHERE ROWNUM = 1
      #SQL_END
      sql = &amp;lt;&amp;lt;-SQL_END
      SELECT * FROM (
        SELECT DBMS_LOB.GETLENGTH(#{column_name}) AS &amp;quot;LENGTH&amp;quot; 
        FROM #{table_name} 
        WHERE DBMS_LOB.GETLENGTH(#{column_name}) IS NOT NULL 
        ORDER BY DBMS_LOB.GETLENGTH(#{column_name}) DESC) 
      WHERE ROWNUM = 1
      SQL_END
      resultset = self.find_by_sql(sql)
      resultset.empty? ? nil : resultset[0].try(:length).try(:to_i)
    rescue =&amp;gt; ex
      puts &amp;quot;Failed for '#{sql}'\nwith #{ex.class}: #{ex.backtrace}&amp;quot;
    end
  end
end

ActiveRecord::Base.connection.tables.each do |table_name|
  begin
    #puts &amp;quot;classifying #{table_name}&amp;quot;
    model = nil
    model_name = table_name.classify
    begin
      model = eval(model_name)
    rescue =&amp;gt; ex2
      puts &amp;quot;There was a table #{table_name} but no corresponding model named #{model_name}, so we're cowardly abandoning attempts to check for CLOBs in it.&amp;quot;
    end
    if model
      #puts &amp;quot;iterating #{table_name} columns&amp;quot;
      model.columns.each do |column|
        #puts &amp;quot;checking #{column.name}&amp;quot;
        if column.sql_type == &amp;quot;CLOB&amp;quot;
          puts &amp;quot;#{table_name}.#{column.name} is a CLOB. Maybe it could be a VARCHAR2(#{MaxLengthUtility.find_max_length(table_name, column.name)})&amp;quot;
        end
      end
    end
  rescue =&amp;gt; ex
    puts &amp;quot;Failed for #{table_name} with #{ex.class}: #{ex.backtrace}&amp;quot;
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
See also:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://emphaticsolutions.com/2008/05/22/connecting-to-oracle-from-ruby-on-rails.html"&gt;Connecting to Oracle from Ruby on Rails&lt;/a&gt; - lists ActiveRecord types and corresponding Oracle types&lt;/li&gt;
&lt;li&gt;&lt;a href="http://snippets.dzone.com/posts/show/3022"&gt;Switch Oracle CLOB to VARCHAR2&lt;/a&gt; - example code (not migration, but could be used in migration) for conversion&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dcmanges.com/blog/13"&gt;Oracle CLOBs in Rails&lt;/a&gt; - data about slowness related to use of CLOBs (text) vs VARCHAR2 (string)&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7511300352336111218?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7511300352336111218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7511300352336111218' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7511300352336111218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7511300352336111218'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/ruby-script-to-identify-clobs-and.html' title='Ruby Script to Identify CLOBs and Required Length of VARCHAR2 for Conversion'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3548753135803673207</id><published>2010-09-10T11:07:00.026-04:00</published><updated>2010-09-10T15:27:02.236-04:00</updated><title type='text'>How to Find the Maximum Length Value in a CLOB Column in Oracle</title><content type='html'>If you want to convert CLOB to VARCHAR2 for speed or to avoid LOB related complication in queries, you might need to know how long the VARCHAR2 will need to be.
&lt;p/&gt;
To determine the length of the CLOB column in characters based on getting the actual value of the CLOB (which you'd need to do if you converted to VARCHAR2), use this query:
&lt;pre&gt;&lt;code&gt;
SELECT * FROM (
  SELECT LENGTH(DBMS_LOB.SUBSTR(your_column_name)) 
  AS &amp;quot;LENGTH&amp;quot; 
  FROM your_table_name 
  WHERE LENGTH(DBMS_LOB.SUBSTR(your_column_name)) IS NOT NULL 
  ORDER BY LENGTH(DBMS_LOB.SUBSTR(your_column_name)) DESC)
WHERE ROWNUM = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
If you're using an older version of Oracle pre-8i, you'll need to use another method than rownum = 1 to get the value with the largest size, in which case you should read:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.orafaq.com/faq/how_does_one_select_the_top_n_rows_from_a_table"&gt;How does one select the TOP N rows from a table?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
If you get:
&lt;pre&gt;&lt;code&gt;
 [Error Code: 6502, SQL State: 65000]
 ORA-06502: PL/SQL: numeric or value error: 
 character string buffer too small
 ORA-06512: at line 1
&lt;/code&gt;&lt;/pre&gt;
I &lt;em&gt;think&lt;/em&gt; it means the CLOB is larger than can be held than in the variable Oracle uses to hold the result from DBMS_LOB.SUBSTR(your_column_name). I think that max length is 4000, by default. I skimmed results against our data and length got close to but never over 3999 without an error. I believe you might be able to add an additional argument specifying length.
&lt;p/&gt;
But if you need CLOB length regardless of whether you could convert, use DBMS_LOB.GETLENGTH(your_column_name) to get the length. I saw some say the following might work to get large substr out: DBMS_LOB.SUBSTR(your_column_name, 4000, 1), DBMS_LOB.SUBSTR(your_column_name, 4000, 4001), DBMS_LOB.SUBSTR(your_column_name, 4000, 8001), ...
&lt;pre&gt;&lt;code&gt;
SELECT * FROM (
  SELECT DBMS_LOB.GETLENGTH(my_column_name) AS "LENGTH" 
  FROM my_table_name 
  WHERE DBMS_LOB.GETLENGTH(my_column_name) IS NOT NULL 
  ORDER BY DBMS_LOB.GETLENGTH(my_column_name) DESC) 
WHERE ROWNUM = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
See:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://psoug.org/reference/dbms_lob.html"&gt;Oracle DBMS_LOB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3548753135803673207?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3548753135803673207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3548753135803673207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3548753135803673207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3548753135803673207'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/09/how-to-find-maximum-length-value-in.html' title='How to Find the Maximum Length Value in a CLOB Column in Oracle'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2331725751948762558</id><published>2010-08-30T16:22:00.004-04:00</published><updated>2010-08-30T16:25:00.743-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails activerecord id ORA-02289 oracle'/><title type='text'>How to Fix ActiveRecord::StatementInvalid (OCIError: ORA-02289: sequence does not exist: select your_model_name_seq.nextval id from dual)</title><content type='html'>Was getting the following error until I noticed that I'd accidentally defined the model's table in the migration with :id =&amp;gt; false (which accidentally crept in there, so was good that it had an error). To fix, I did rake db:rollback, removed the :id =&amp;gt; false from the create table, and did rake rb:migrate.
&lt;pre&gt;&lt;code&gt;
ActiveRecord::StatementInvalid (OCIError: ORA-02289: sequence does not exist: select your_model_name_seq.nextval id from dual):
  vendor/gems/activerecord-oracle_enhanced-adapter-1.2.0/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:927:in `select'
  vendor/gems/activerecord-oracle_enhanced-adapter-1.2.0/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:464:in `next_sequence_value'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
  /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2331725751948762558?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2331725751948762558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2331725751948762558' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2331725751948762558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2331725751948762558'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/08/how-to-fix-activerecordstatementinvalid.html' title='How to Fix ActiveRecord::StatementInvalid (OCIError: ORA-02289: sequence does not exist: select your_model_name_seq.nextval id from dual)'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6470361035803628681</id><published>2010-08-26T10:44:00.001-04:00</published><updated>2010-08-26T10:45:29.566-04:00</updated><title type='text'>Make Ruby Array to_s Make Comma-delimited Strings</title><content type='html'>If you want to_s when called to array to always output comma-delimited array values, try the following from a &lt;a href="http://www.justskins.com/forums/array-and-hash-to_s-24344.html"&gt;post by Ben Giddings&lt;/a&gt; (long ago in 2003):
&lt;pre&gt;&lt;code&gt;
$, = ", "
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
There's also another solution &lt;a href="http://www.justskins.com/forums/array-and-hash-to_s-24344.html"&gt;in there&lt;/a&gt; along with Yukihiro Matsumoto's response to both. It's somewhat annoying to always type .join(', ') when printing out an array, so I might start to use this, at least when using irb.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6470361035803628681?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6470361035803628681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6470361035803628681' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6470361035803628681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6470361035803628681'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/08/make-ruby-array-tos-make-comma.html' title='Make Ruby Array to_s Make Comma-delimited Strings'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4889448330936232408</id><published>2010-08-26T10:26:00.006-04:00</published><updated>2011-01-04T13:19:27.694-05:00</updated><title type='text'>Straight SQL to Oracle via Ruby Script with RBI</title><content type='html'>If you have some straight SQL to run against Oracle, and want to execute it in Ruby in a script sans Rails, try DBI. It's one of the older projects, but works fine for purposes of a script.
&lt;p/&gt;
Put this into a file called sql.rb. This is heavily based on the MySQL example in &lt;a href="http://www.kitebird.com/articles/ruby-dbi.html"&gt;Using the Ruby DBI Module&lt;/a&gt; by Paul DuBois rev. 1.03 (2006-11-28):
&lt;pre&gt;&lt;code&gt;
#!/usr/bin/ruby -w
# requires you to have previously run:
# gem install dbi
require 'rubygems'
require 'dbi'
puts &amp;quot;Loaded DBI #{DBI::VERSION}&amp;quot;

begin
  #format for Oracle is DBI.connect('DBI:OCI8://host:port/service_name','username','password')
  dbh = DBI.connect('DBI:OCI8://db.acme.org:1234/ACMETEST.WORLD','jdoe','passwd')

  # get server version string and display it
  row = dbh.select_one(&amp;quot;select version from v$instance&amp;quot;)
  puts &amp;quot;Server version: #{row[0]}&amp;quot;
rescue DBI::DatabaseError =&amp;gt; e
  puts &amp;quot;An error occurred&amp;quot;
  puts &amp;quot;Error code: #{e.err}&amp;quot;
  puts &amp;quot;Error message: #{e.errstr}&amp;quot;
ensure
  # disconnect from server
  dbh.disconnect if dbh
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then:
&lt;pre&gt;&lt;code&gt;
chmod +x sql.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Modify that file to change the connect string. Notice that the example "ACMETEST.WORLD" is a service_name. So, if you have a service name defined in tnsnames.ora, you could use that, but you don't have to (for example: I just appended ".WORLD" to convert the SID to a service name).
&lt;p/&gt;
If you haven't already, install dbi:
&lt;pre&gt;&lt;code&gt;
gem install dbi
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then execute:
&lt;pre&gt;&lt;code&gt;
./sql.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Be sure to use "prepare" to prepare statements if you can't trust the data going into the values in your query. For example:
&lt;pre&gt;&lt;code&gt;
  prepared_query = dbh.prepare(&amp;quot;select email from user where name = ?&amp;quot;)
  row = dbh.select_one(prepared_query, name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
For more info, see &lt;a href="http://www.kitebird.com/articles/ruby-dbi.html"&gt;Using the Ruby DBI Module&lt;/a&gt; which provides some info on how to use it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4889448330936232408?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4889448330936232408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4889448330936232408' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4889448330936232408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4889448330936232408'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/08/straight-sql-to-oracle-via-ruby-script.html' title='Straight SQL to Oracle via Ruby Script with RBI'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-854882457762997431</id><published>2010-08-20T15:54:00.003-04:00</published><updated>2010-12-22T13:30:29.770-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shib shibboleth shibbolize uportal jmeter test login auth authn authorization'/><title type='text'>Using JMeter to Test Shibboleth Login to uPortal</title><content type='html'>The following is a generified JMeter 2.4 test to use as a template so that you can test Shibboleth login to uPortal. This is based heavily on a script provided by Stan F. locally. Note that the last step in the process is to again get the uPortal Login page, as that actually logs you into uPortal, not just Shibboleth.
&lt;p/&gt;
Save to a file like portal_test.jmx and open in &lt;a href="http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi"&gt;JMeter&lt;/a&gt;. Then just edit the file and replace "portal.acme.edu" with your uPortal server, "my.shibboleth.idp.acme.edu" with your Shibboleth IdP, and the two "replace this..." strings with appropriate content. By default, it runs as a monitor (indefinitely), writing errors out as files into the bin directory of JMeter, but you can tweak it however you wish to make it a real load test, rather than a simple monitoring script.
&lt;p/&gt;
(Note: at first I was going to use the Mailer Visualizer to send emails with info when it failed, but that action still seems fairly limited in 2.4.)
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;jmeterTestPlan version=&amp;quot;1.2&amp;quot; properties=&amp;quot;2.1&amp;quot;&amp;gt;
  &amp;lt;hashTree&amp;gt;
    &amp;lt;TestPlan guiclass=&amp;quot;TestPlanGui&amp;quot; testclass=&amp;quot;TestPlan&amp;quot; testname=&amp;quot;My Test Plan&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
      &amp;lt;boolProp name=&amp;quot;TestPlan.functional_mode&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
      &amp;lt;collectionProp name=&amp;quot;TestPlan.thread_groups&amp;quot;/&amp;gt;
      &amp;lt;elementProp name=&amp;quot;TestPlan.user_defined_variables&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;ArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
        &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;/&amp;gt;
      &amp;lt;/elementProp&amp;gt;
      &amp;lt;boolProp name=&amp;quot;TestPlan.serialize_threadgroups&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
      &amp;lt;stringProp name=&amp;quot;TestPlan.comments&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
      &amp;lt;stringProp name=&amp;quot;TestPlan.user_define_classpath&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
    &amp;lt;/TestPlan&amp;gt;
    &amp;lt;hashTree&amp;gt;
      &amp;lt;ThreadGroup guiclass=&amp;quot;ThreadGroupGui&amp;quot; testclass=&amp;quot;ThreadGroup&amp;quot; testname=&amp;quot;Thread Group&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
        &amp;lt;elementProp name=&amp;quot;ThreadGroup.main_controller&amp;quot; elementType=&amp;quot;LoopController&amp;quot; guiclass=&amp;quot;LoopControlPanel&amp;quot; testclass=&amp;quot;LoopController&amp;quot; testname=&amp;quot;Loop Controller&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;boolProp name=&amp;quot;LoopController.continue_forever&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
          &amp;lt;intProp name=&amp;quot;LoopController.loops&amp;quot;&amp;gt;-1&amp;lt;/intProp&amp;gt;
        &amp;lt;/elementProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;ThreadGroup.num_threads&amp;quot;&amp;gt;1&amp;lt;/stringProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;ThreadGroup.ramp_time&amp;quot;&amp;gt;1&amp;lt;/stringProp&amp;gt;
        &amp;lt;longProp name=&amp;quot;ThreadGroup.start_time&amp;quot;&amp;gt;1276016381000&amp;lt;/longProp&amp;gt;
        &amp;lt;longProp name=&amp;quot;ThreadGroup.end_time&amp;quot;&amp;gt;1276016381000&amp;lt;/longProp&amp;gt;
        &amp;lt;boolProp name=&amp;quot;ThreadGroup.scheduler&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;ThreadGroup.on_sample_error&amp;quot;&amp;gt;continue&amp;lt;/stringProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;ThreadGroup.duration&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;ThreadGroup.delay&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
      &amp;lt;/ThreadGroup&amp;gt;
      &amp;lt;hashTree&amp;gt;
        &amp;lt;GaussianRandomTimer guiclass=&amp;quot;GaussianRandomTimerGui&amp;quot; testclass=&amp;quot;GaussianRandomTimer&amp;quot; testname=&amp;quot;Gaussian Random Timer&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;stringProp name=&amp;quot;ConstantTimer.delay&amp;quot;&amp;gt;300&amp;lt;/stringProp&amp;gt;
          &amp;lt;stringProp name=&amp;quot;RandomTimer.range&amp;quot;&amp;gt;300&amp;lt;/stringProp&amp;gt;
        &amp;lt;/GaussianRandomTimer&amp;gt;
        &amp;lt;hashTree/&amp;gt;
        &amp;lt;CookieManager guiclass=&amp;quot;CookiePanel&amp;quot; testclass=&amp;quot;CookieManager&amp;quot; testname=&amp;quot;HTTP Cookie Manager&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;collectionProp name=&amp;quot;CookieManager.cookies&amp;quot;/&amp;gt;
          &amp;lt;boolProp name=&amp;quot;CookieManager.clearEachIteration&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
        &amp;lt;/CookieManager&amp;gt;
        &amp;lt;hashTree/&amp;gt;
        &amp;lt;UserParameters guiclass=&amp;quot;UserParametersGui&amp;quot; testclass=&amp;quot;UserParameters&amp;quot; testname=&amp;quot;User Parameters&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;boolProp name=&amp;quot;TestElement.per_iteration&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
          &amp;lt;collectionProp name=&amp;quot;UserParameters.names&amp;quot;&amp;gt;
            &amp;lt;stringProp name=&amp;quot;VIEWSTATE&amp;quot;&amp;gt;VIEWSTATE&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;jsessionid&amp;quot;&amp;gt;jsessionid&amp;lt;/stringProp&amp;gt;
          &amp;lt;/collectionProp&amp;gt;
          &amp;lt;collectionProp name=&amp;quot;UserParameters.thread_values&amp;quot;&amp;gt;
            &amp;lt;collectionProp name=&amp;quot;745697&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;/collectionProp&amp;gt;
          &amp;lt;/collectionProp&amp;gt;
          &amp;lt;boolProp name=&amp;quot;UserParameters.per_iteration&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
        &amp;lt;/UserParameters&amp;gt;
        &amp;lt;hashTree/&amp;gt;
        &amp;lt;HeaderManager guiclass=&amp;quot;HeaderPanel&amp;quot; testclass=&amp;quot;HeaderManager&amp;quot; testname=&amp;quot;HTTP Header Manager&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;collectionProp name=&amp;quot;HeaderManager.headers&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;&amp;quot; elementType=&amp;quot;Header&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.name&amp;quot;&amp;gt;User-Agent&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.value&amp;quot;&amp;gt;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3&amp;lt;/stringProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;elementProp name=&amp;quot;&amp;quot; elementType=&amp;quot;Header&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.name&amp;quot;&amp;gt;Accept&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.value&amp;quot;&amp;gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&amp;lt;/stringProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;elementProp name=&amp;quot;&amp;quot; elementType=&amp;quot;Header&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.name&amp;quot;&amp;gt;Accept-Language&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.value&amp;quot;&amp;gt;en-us,en;q=0.5&amp;lt;/stringProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;elementProp name=&amp;quot;&amp;quot; elementType=&amp;quot;Header&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.name&amp;quot;&amp;gt;Accept-Encoding&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.value&amp;quot;&amp;gt;gzip,deflate&amp;lt;/stringProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;elementProp name=&amp;quot;&amp;quot; elementType=&amp;quot;Header&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.name&amp;quot;&amp;gt;Accept-Charset&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Header.value&amp;quot;&amp;gt;ISO-8859-1,utf-8;q=0.7,*;q=0.7&amp;lt;/stringProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
          &amp;lt;/collectionProp&amp;gt;
        &amp;lt;/HeaderManager&amp;gt;
        &amp;lt;hashTree/&amp;gt;
        &amp;lt;LoopController guiclass=&amp;quot;LoopControlPanel&amp;quot; testclass=&amp;quot;LoopController&amp;quot; testname=&amp;quot;Step 1&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;boolProp name=&amp;quot;LoopController.continue_forever&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
          &amp;lt;stringProp name=&amp;quot;LoopController.loops&amp;quot;&amp;gt;1&amp;lt;/stringProp&amp;gt;
        &amp;lt;/LoopController&amp;gt;
        &amp;lt;hashTree&amp;gt;
          &amp;lt;HTTPSampler guiclass=&amp;quot;HttpTestSampleGui&amp;quot; testclass=&amp;quot;HTTPSampler&amp;quot; testname=&amp;quot;https://portal.acme.edu/uPortal&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;HTTPsampler.Arguments&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;HTTPArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;/&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.domain&amp;quot;&amp;gt;portal.acme.edu&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.port&amp;quot;&amp;gt;443&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.connect_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.response_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.protocol&amp;quot;&amp;gt;https&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.contentEncoding&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.path&amp;quot;&amp;gt;/uPortal&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.method&amp;quot;&amp;gt;GET&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.follow_redirects&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.auto_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.use_keepalive&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.DO_MULTIPART_POST&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_NAME&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_FIELD&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.mimetype&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.monitor&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.embedded_url_re&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
          &amp;lt;/HTTPSampler&amp;gt;
          &amp;lt;hashTree/&amp;gt;
          &amp;lt;HTTPSampler guiclass=&amp;quot;HttpTestSampleGui&amp;quot; testclass=&amp;quot;HTTPSampler&amp;quot; testname=&amp;quot;https://portal.acme.edu/uPortal/Login&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;HTTPsampler.Arguments&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;HTTPArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;&amp;gt;
                &amp;lt;elementProp name=&amp;quot;Login&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;Login&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;Login&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.domain&amp;quot;&amp;gt;portal.acme.edu&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.port&amp;quot;&amp;gt;443&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.connect_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.response_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.protocol&amp;quot;&amp;gt;https&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.contentEncoding&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.path&amp;quot;&amp;gt;/uPortal/Login&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.method&amp;quot;&amp;gt;POST&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.follow_redirects&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.auto_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.use_keepalive&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.DO_MULTIPART_POST&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_NAME&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_FIELD&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.mimetype&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.monitor&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.embedded_url_re&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
          &amp;lt;/HTTPSampler&amp;gt;
          &amp;lt;hashTree/&amp;gt;
          &amp;lt;HTTPSampler guiclass=&amp;quot;HttpTestSampleGui&amp;quot; testclass=&amp;quot;HTTPSampler&amp;quot; testname=&amp;quot;https://my.shibboleth.idp.acme.edu/idp/Authn/UserPassword&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;HTTPsampler.Arguments&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;HTTPArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;&amp;gt;
                &amp;lt;elementProp name=&amp;quot;j_username&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;some_user&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;j_username&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
                &amp;lt;elementProp name=&amp;quot;j_password&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;some_password&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;j_password&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
                &amp;lt;elementProp name=&amp;quot;Submit&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;Enter&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;Submit&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.domain&amp;quot;&amp;gt;my.shibboleth.idp.acme.edu&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.port&amp;quot;&amp;gt;443&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.connect_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.response_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.protocol&amp;quot;&amp;gt;https&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.contentEncoding&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.path&amp;quot;&amp;gt;/idp/Authn/UserPassword&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.method&amp;quot;&amp;gt;POST&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.follow_redirects&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.auto_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.use_keepalive&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.DO_MULTIPART_POST&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_NAME&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_FIELD&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.mimetype&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.monitor&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.embedded_url_re&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
          &amp;lt;/HTTPSampler&amp;gt;
          &amp;lt;hashTree&amp;gt;
            &amp;lt;XPathExtractor guiclass=&amp;quot;XPathExtractorGui&amp;quot; testclass=&amp;quot;XPathExtractor&amp;quot; testname=&amp;quot;XPath Extractor&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.default&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.refname&amp;quot;&amp;gt;samlresponse&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.xpathQuery&amp;quot;&amp;gt;/html//input[@name=&amp;amp;quot;SAMLResponse&amp;amp;quot;]/@value&amp;lt;/stringProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;XPathExtractor.tolerant&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;XPathExtractor.namespace&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;/XPathExtractor&amp;gt;
            &amp;lt;hashTree/&amp;gt;
            &amp;lt;XPathExtractor guiclass=&amp;quot;XPathExtractorGui&amp;quot; testclass=&amp;quot;XPathExtractor&amp;quot; testname=&amp;quot;XPath Extractor&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.default&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.refname&amp;quot;&amp;gt;relaystate&amp;lt;/stringProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;XPathExtractor.xpathQuery&amp;quot;&amp;gt;/html/input[@name=&amp;amp;quot;RelayState&amp;amp;quot;]/@value&amp;lt;/stringProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;XPathExtractor.tolerant&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;XPathExtractor.namespace&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;/XPathExtractor&amp;gt;
            &amp;lt;hashTree/&amp;gt;
            &amp;lt;ResponseAssertion guiclass=&amp;quot;AssertionGui&amp;quot; testclass=&amp;quot;ResponseAssertion&amp;quot; testname=&amp;quot;Response Assertion&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Asserion.test_strings&amp;quot;&amp;gt;
                &amp;lt;stringProp name=&amp;quot;-274265185&amp;quot;&amp;gt;press the Continue button&amp;lt;/stringProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Assertion.test_field&amp;quot;&amp;gt;Assertion.response_data&amp;lt;/stringProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;Assertion.assume_success&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
              &amp;lt;intProp name=&amp;quot;Assertion.test_type&amp;quot;&amp;gt;2&amp;lt;/intProp&amp;gt;
            &amp;lt;/ResponseAssertion&amp;gt;
            &amp;lt;hashTree/&amp;gt;
          &amp;lt;/hashTree&amp;gt;
          &amp;lt;HTTPSampler guiclass=&amp;quot;HttpTestSampleGui&amp;quot; testclass=&amp;quot;HTTPSampler&amp;quot; testname=&amp;quot;https://portal.acme.edu/Shibboleth.sso/SAML2/POST&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;HTTPsampler.Arguments&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;HTTPArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;&amp;gt;
                &amp;lt;elementProp name=&amp;quot;RelayState&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;${relaystate}&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;RelayState&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
                &amp;lt;elementProp name=&amp;quot;SAMLResponse&amp;quot; elementType=&amp;quot;HTTPArgument&amp;quot;&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;HTTPArgument.always_encode&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.value&amp;quot;&amp;gt;${samlresponse}&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.name&amp;quot;&amp;gt;SAMLResponse&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.metadata&amp;quot;&amp;gt;=&amp;lt;/stringProp&amp;gt;
                  &amp;lt;stringProp name=&amp;quot;Argument.use_equals&amp;quot;&amp;gt;true&amp;lt;/stringProp&amp;gt;
                  &amp;lt;boolProp name=&amp;quot;HTTPArgument.use_equals&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
                &amp;lt;/elementProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.domain&amp;quot;&amp;gt;portal.acme.edu&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.port&amp;quot;&amp;gt;443&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.connect_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.response_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.protocol&amp;quot;&amp;gt;https&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.contentEncoding&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.path&amp;quot;&amp;gt;/Shibboleth.sso/SAML2/POST&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.method&amp;quot;&amp;gt;POST&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.follow_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.auto_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.use_keepalive&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.DO_MULTIPART_POST&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_NAME&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_FIELD&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.mimetype&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.monitor&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.embedded_url_re&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
          &amp;lt;/HTTPSampler&amp;gt;
          &amp;lt;hashTree/&amp;gt;
          &amp;lt;HTTPSampler guiclass=&amp;quot;HttpTestSampleGui&amp;quot; testclass=&amp;quot;HTTPSampler&amp;quot; testname=&amp;quot;https://portal.acme.edu/uPortal/Login&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;elementProp name=&amp;quot;HTTPsampler.Arguments&amp;quot; elementType=&amp;quot;Arguments&amp;quot; guiclass=&amp;quot;HTTPArgumentsPanel&amp;quot; testclass=&amp;quot;Arguments&amp;quot; testname=&amp;quot;Argument List&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Arguments.arguments&amp;quot;/&amp;gt;
            &amp;lt;/elementProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.domain&amp;quot;&amp;gt;portal.acme.edu&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.port&amp;quot;&amp;gt;443&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.connect_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.response_timeout&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.protocol&amp;quot;&amp;gt;https&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.contentEncoding&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.path&amp;quot;&amp;gt;/uPortal/Login&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.method&amp;quot;&amp;gt;GET&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.follow_redirects&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.auto_redirects&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.use_keepalive&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.DO_MULTIPART_POST&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_NAME&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.FILE_FIELD&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.mimetype&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
            &amp;lt;boolProp name=&amp;quot;HTTPSampler.monitor&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;HTTPSampler.embedded_url_re&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
          &amp;lt;/HTTPSampler&amp;gt;
          &amp;lt;hashTree&amp;gt;
            &amp;lt;ResponseAssertion guiclass=&amp;quot;AssertionGui&amp;quot; testclass=&amp;quot;ResponseAssertion&amp;quot; testname=&amp;quot;Response Assertion&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Asserion.test_strings&amp;quot;&amp;gt;
                &amp;lt;stringProp name=&amp;quot;33350373&amp;quot;&amp;gt;replace this with text that should be in a fully loaded page&amp;lt;/stringProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Assertion.test_field&amp;quot;&amp;gt;Assertion.response_data&amp;lt;/stringProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;Assertion.assume_success&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
              &amp;lt;intProp name=&amp;quot;Assertion.test_type&amp;quot;&amp;gt;16&amp;lt;/intProp&amp;gt;
            &amp;lt;/ResponseAssertion&amp;gt;
            &amp;lt;hashTree/&amp;gt;
            &amp;lt;ResponseAssertion guiclass=&amp;quot;AssertionGui&amp;quot; testclass=&amp;quot;ResponseAssertion&amp;quot; testname=&amp;quot;Response Assertion&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
              &amp;lt;collectionProp name=&amp;quot;Asserion.test_strings&amp;quot;&amp;gt;
                &amp;lt;stringProp name=&amp;quot;-75219048&amp;quot;&amp;gt;replace this with text from a portlet that you would only see if you logged in&amp;lt;/stringProp&amp;gt;
              &amp;lt;/collectionProp&amp;gt;
              &amp;lt;stringProp name=&amp;quot;Assertion.test_field&amp;quot;&amp;gt;Assertion.response_data&amp;lt;/stringProp&amp;gt;
              &amp;lt;boolProp name=&amp;quot;Assertion.assume_success&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
              &amp;lt;intProp name=&amp;quot;Assertion.test_type&amp;quot;&amp;gt;2&amp;lt;/intProp&amp;gt;
            &amp;lt;/ResponseAssertion&amp;gt;
            &amp;lt;hashTree/&amp;gt;
          &amp;lt;/hashTree&amp;gt;
          &amp;lt;UniformRandomTimer guiclass=&amp;quot;UniformRandomTimerGui&amp;quot; testclass=&amp;quot;UniformRandomTimer&amp;quot; testname=&amp;quot;Uniform Random Timer&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
            &amp;lt;stringProp name=&amp;quot;ConstantTimer.delay&amp;quot;&amp;gt;3000&amp;lt;/stringProp&amp;gt;
            &amp;lt;stringProp name=&amp;quot;RandomTimer.range&amp;quot;&amp;gt;15000.0&amp;lt;/stringProp&amp;gt;
          &amp;lt;/UniformRandomTimer&amp;gt;
          &amp;lt;hashTree/&amp;gt;
        &amp;lt;/hashTree&amp;gt;
        &amp;lt;ResultSaver guiclass=&amp;quot;ResultSaverGui&amp;quot; testclass=&amp;quot;ResultSaver&amp;quot; testname=&amp;quot;Save Responses to a file&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
          &amp;lt;stringProp name=&amp;quot;FileSaver.filename&amp;quot;&amp;gt;portal_error&amp;lt;/stringProp&amp;gt;
          &amp;lt;boolProp name=&amp;quot;FileSaver.errorsonly&amp;quot;&amp;gt;true&amp;lt;/boolProp&amp;gt;
          &amp;lt;boolProp name=&amp;quot;FileSaver.skipautonumber&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
          &amp;lt;boolProp name=&amp;quot;FileSaver.skipsuffix&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
          &amp;lt;boolProp name=&amp;quot;FileSaver.successonly&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
        &amp;lt;/ResultSaver&amp;gt;
        &amp;lt;hashTree/&amp;gt;
      &amp;lt;/hashTree&amp;gt;
      &amp;lt;ResultCollector guiclass=&amp;quot;ViewResultsFullVisualizer&amp;quot; testclass=&amp;quot;ResultCollector&amp;quot; testname=&amp;quot;View Results Tree&amp;quot; enabled=&amp;quot;false&amp;quot;&amp;gt;
        &amp;lt;boolProp name=&amp;quot;ResultCollector.error_logging&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
        &amp;lt;objProp&amp;gt;
          &amp;lt;name&amp;gt;saveConfig&amp;lt;/name&amp;gt;
          &amp;lt;value class=&amp;quot;SampleSaveConfiguration&amp;quot;&amp;gt;
            &amp;lt;time&amp;gt;true&amp;lt;/time&amp;gt;
            &amp;lt;latency&amp;gt;true&amp;lt;/latency&amp;gt;
            &amp;lt;timestamp&amp;gt;true&amp;lt;/timestamp&amp;gt;
            &amp;lt;success&amp;gt;true&amp;lt;/success&amp;gt;
            &amp;lt;label&amp;gt;true&amp;lt;/label&amp;gt;
            &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;
            &amp;lt;message&amp;gt;true&amp;lt;/message&amp;gt;
            &amp;lt;threadName&amp;gt;true&amp;lt;/threadName&amp;gt;
            &amp;lt;dataType&amp;gt;true&amp;lt;/dataType&amp;gt;
            &amp;lt;encoding&amp;gt;false&amp;lt;/encoding&amp;gt;
            &amp;lt;assertions&amp;gt;true&amp;lt;/assertions&amp;gt;
            &amp;lt;subresults&amp;gt;true&amp;lt;/subresults&amp;gt;
            &amp;lt;responseData&amp;gt;false&amp;lt;/responseData&amp;gt;
            &amp;lt;samplerData&amp;gt;false&amp;lt;/samplerData&amp;gt;
            &amp;lt;xml&amp;gt;true&amp;lt;/xml&amp;gt;
            &amp;lt;fieldNames&amp;gt;false&amp;lt;/fieldNames&amp;gt;
            &amp;lt;responseHeaders&amp;gt;false&amp;lt;/responseHeaders&amp;gt;
            &amp;lt;requestHeaders&amp;gt;false&amp;lt;/requestHeaders&amp;gt;
            &amp;lt;responseDataOnError&amp;gt;false&amp;lt;/responseDataOnError&amp;gt;
            &amp;lt;saveAssertionResultsFailureMessage&amp;gt;false&amp;lt;/saveAssertionResultsFailureMessage&amp;gt;
            &amp;lt;assertionsResultsToSave&amp;gt;0&amp;lt;/assertionsResultsToSave&amp;gt;
            &amp;lt;bytes&amp;gt;true&amp;lt;/bytes&amp;gt;
          &amp;lt;/value&amp;gt;
        &amp;lt;/objProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;filename&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
      &amp;lt;/ResultCollector&amp;gt;
      &amp;lt;hashTree/&amp;gt;
      &amp;lt;ResultCollector guiclass=&amp;quot;SummaryReport&amp;quot; testclass=&amp;quot;ResultCollector&amp;quot; testname=&amp;quot;Summary Report&amp;quot; enabled=&amp;quot;true&amp;quot;&amp;gt;
        &amp;lt;boolProp name=&amp;quot;ResultCollector.error_logging&amp;quot;&amp;gt;false&amp;lt;/boolProp&amp;gt;
        &amp;lt;objProp&amp;gt;
          &amp;lt;name&amp;gt;saveConfig&amp;lt;/name&amp;gt;
          &amp;lt;value class=&amp;quot;SampleSaveConfiguration&amp;quot;&amp;gt;
            &amp;lt;time&amp;gt;true&amp;lt;/time&amp;gt;
            &amp;lt;latency&amp;gt;true&amp;lt;/latency&amp;gt;
            &amp;lt;timestamp&amp;gt;true&amp;lt;/timestamp&amp;gt;
            &amp;lt;success&amp;gt;true&amp;lt;/success&amp;gt;
            &amp;lt;label&amp;gt;true&amp;lt;/label&amp;gt;
            &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;
            &amp;lt;message&amp;gt;true&amp;lt;/message&amp;gt;
            &amp;lt;threadName&amp;gt;true&amp;lt;/threadName&amp;gt;
            &amp;lt;dataType&amp;gt;true&amp;lt;/dataType&amp;gt;
            &amp;lt;encoding&amp;gt;false&amp;lt;/encoding&amp;gt;
            &amp;lt;assertions&amp;gt;true&amp;lt;/assertions&amp;gt;
            &amp;lt;subresults&amp;gt;true&amp;lt;/subresults&amp;gt;
            &amp;lt;responseData&amp;gt;false&amp;lt;/responseData&amp;gt;
            &amp;lt;samplerData&amp;gt;false&amp;lt;/samplerData&amp;gt;
            &amp;lt;xml&amp;gt;true&amp;lt;/xml&amp;gt;
            &amp;lt;fieldNames&amp;gt;false&amp;lt;/fieldNames&amp;gt;
            &amp;lt;responseHeaders&amp;gt;false&amp;lt;/responseHeaders&amp;gt;
            &amp;lt;requestHeaders&amp;gt;false&amp;lt;/requestHeaders&amp;gt;
            &amp;lt;responseDataOnError&amp;gt;false&amp;lt;/responseDataOnError&amp;gt;
            &amp;lt;saveAssertionResultsFailureMessage&amp;gt;false&amp;lt;/saveAssertionResultsFailureMessage&amp;gt;
            &amp;lt;assertionsResultsToSave&amp;gt;0&amp;lt;/assertionsResultsToSave&amp;gt;
            &amp;lt;bytes&amp;gt;true&amp;lt;/bytes&amp;gt;
          &amp;lt;/value&amp;gt;
        &amp;lt;/objProp&amp;gt;
        &amp;lt;stringProp name=&amp;quot;filename&amp;quot;&amp;gt;&amp;lt;/stringProp&amp;gt;
      &amp;lt;/ResultCollector&amp;gt;
      &amp;lt;hashTree/&amp;gt;
    &amp;lt;/hashTree&amp;gt;
  &amp;lt;/hashTree&amp;gt;
&amp;lt;/jmeterTestPlan&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-854882457762997431?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/854882457762997431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=854882457762997431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/854882457762997431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/854882457762997431'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/08/using-jmeter-to-test-shibboleth-login.html' title='Using JMeter to Test Shibboleth Login to uPortal'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-876273449123579009</id><published>2010-08-11T10:33:00.012-04:00</published><updated>2010-08-11T11:19:24.278-04:00</updated><title type='text'>Nil-Safe Sorting in Ruby Made Easy</title><content type='html'>I'm not sure why nil doesn't support &lt;=&gt;. In most sorting cases, nil is less than everything else, so it would seem safe enough if it were extended with that. You've run into this issue if you get:
&lt;pre&gt;&lt;code&gt;
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.&amp;lt;=&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
So, what's the workaround?
&lt;p/&gt;
Say you want to sort an array of task assignments their project name. My first hack was to write a lot of code like the following to try to get around it:
&lt;pre&gt;&lt;code&gt;
task_assignment.sort { |x,y|
  a = x.try(:project).try(:name)
  b = y.try(:project).try(:name)
  if a &amp;amp;&amp;amp; b
    a &amp;lt;=&amp;gt; b
  elsif !a &amp;amp;&amp;amp; !b
    0
  else
    left ? 1 : -1
  end
}
&lt;/code&gt;&lt;/pre&gt;
I knew this was a little long, so I spoke with Jim who showed me a much cleaner method:
&lt;pre&gt;&lt;code&gt;
task_assignment.sort_by { |ta| ta.try(:project).try(:name) || '' }
&lt;/code&gt;&lt;/pre&gt;
With this code, nil, a task assignment without a project, or a project without a name are equivalent to a task assignment with a project name of ''. It's not functionally equivalent to the code above it that would weigh nil even less than '', but it's fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-876273449123579009?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/876273449123579009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=876273449123579009' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/876273449123579009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/876273449123579009'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/08/nil-safe-sorting-in-ruby-made-easy.html' title='Nil-Safe Sorting in Ruby Made Easy'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2710204687004487641</id><published>2010-07-30T17:01:00.014-04:00</published><updated>2011-02-01T09:28:53.785-05:00</updated><title type='text'>Limits of Time in Ruby</title><content type='html'>Was curious about the maximum Time in Ruby and minimum Time in Ruby you could specify via number to the at method, and they seem to be -67768040609636400 and 67768036191694799, at least locally for me in a 64-bit OS X 10.6 environment. The maximum number to not produce a negative year is 67767976233550799:
&lt;pre&gt;&lt;code&gt;
$ ruby -version
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
$ irb
&amp;gt;&amp;gt; Time.at(-67768040609636400)
=&amp;gt; Fri Jan 01 00:00:00 -0500 -2147481748
&amp;gt;&amp;gt; Time.at(-67768040609636401)
ArgumentError: localtime error
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:302:in `inspect'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:302:in `output_value'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:151:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:263:in `signal_status'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:147:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:244:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `loop'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `catch'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:146:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:70:in `start'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:in `catch'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:in `start'
 from /usr/bin/irb:13
Maybe IRB bug!!
&amp;gt;&amp;gt; Time.at(67768036191694799)
=&amp;gt; Wed Dec 31 23:59:59 -0500 -2147481749
&amp;gt;&amp;gt; Time.at(67768036191694800)
ArgumentError: localtime error
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:302:in `inspect'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:302:in `output_value'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:151:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:263:in `signal_status'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:147:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:244:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `loop'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `catch'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:146:in `eval_input'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:70:in `start'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:in `catch'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:in `start'
 from /usr/bin/irb:13
Maybe IRB bug!!
&gt;&gt; Time.at(67767976233550799)
=&gt; Tue Dec 31 23:59:59 -0500 2147483647
&gt;&gt; Time.at(67767976233550800)
=&gt; Wed Jan 01 00:00:00 -0500 -2147483648
&lt;/code&gt;&lt;/pre&gt;
These aren't the limits in JRuby, as you can see here:
&lt;pre&gt;&lt;code&gt;
$ jruby -version
jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2009-11-02 69fbfa3) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_20) [x86_64-java]
$ jirb
irb(main):001:0&amp;gt; Time.at(-67768040609636400)
=&amp;gt; Wed Jan 06 09:43:26 -0500 190734449
irb(main):002:0&amp;gt; Time.at(-67768040609636401)
=&amp;gt; Wed Jan 06 09:43:25 -0500 190734449
irb(main):003:0&amp;gt; Time.at(67768036191694799)
=&amp;gt; Fri Dec 25 14:20:30 -0456 -190730650
irb(main):004:0&amp;gt; Time.at(67768036191694800)
=&amp;gt; Fri Dec 25 14:20:31 -0456 -190730650
&lt;/code&gt;&lt;/pre&gt;
Tested in MacRuby, and it is like the regular Ruby MRI:
&lt;pre&gt;&lt;code&gt;
$ macruby -version
MacRuby version 0.6 (ruby 1.9.0) [universal-darwin10.0, x86_64]
$ macirb
irb(main):001:0&amp;gt; Time.at(67767976233550799)
=&amp;gt; 2147483647-12-31 23:59:59 -0500
irb(main):002:0&amp;gt; Time.at(67767976233550800)
=&amp;gt; -2147483648-01-01 00:00:00 -0500
irb(main):003:0&amp;gt; Time.at(-67768040609636400)
=&amp;gt; -2147481748-01-01 00:00:00 -0500
irb(main):004:0&amp;gt; Time.at(-67768040609636401)
ArgumentError: localtime error

irb(main):005:0&amp;gt; Time.at(67768036191694799)
=&amp;gt; -2147481749-12-31 23:59:59 -0500
irb(main):006:0&amp;gt; Time.at(67768036191694800)
ArgumentError: localtime error

&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
However, these numbers seem to differ in 32-bit environments. In &lt;a href="http://codepad.org"&gt;codepad&lt;/a&gt;, all attempts produce the following error. Steven Hazel of codepad.org stated that this could be a 32-bit OS-specific issue:
&lt;pre&gt;&lt;code&gt;
Line 1:in `at': bignum too big to convert into `long' (RangeError)
&gt;  from t.rb:1
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2710204687004487641?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2710204687004487641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2710204687004487641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2710204687004487641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2710204687004487641'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/limits-of-time-in-ruby.html' title='Limits of Time in Ruby'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3690104504841493493</id><published>2010-07-29T17:09:00.002-04:00</published><updated>2010-07-29T17:11:58.173-04:00</updated><title type='text'>nib Method to Return nil if blank? in Ruby</title><content type='html'>There are a number of solutions out there for returning nil if a variable is nil or blank? in Ruby but I came up with this which I think is easiest. Throw it into some .rb file under lib in your Rails project or just add it to a script.
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
class Object
  
  # Return nil if object.self.blank?, otherwise return object.self
  #
  # Author::  Gary S. Weaver
  
  def nib
    self.blank? ? nil : self
  end

end
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Example usage:
&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; 'John Doe'.nib
=&amp;gt; &amp;quot;John Doe&amp;quot;
&amp;gt;&amp;gt; ' '.nib
=&amp;gt; nil
&amp;gt;&amp;gt; ''.nib
=&amp;gt; nil
&amp;gt;&amp;gt; nil.nib
=&amp;gt; nil
&amp;gt;&amp;gt; 0.nib
=&amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;
This allows you to do the following: (for example, in a view)
&lt;pre&gt;&lt;code&gt;
@director_name.nib || 'no name specified'
&lt;/code&gt;&lt;/pre&gt;
&lt;em&gt;Note: nib stands for "nil if blank?".&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3690104504841493493?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3690104504841493493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3690104504841493493' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3690104504841493493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3690104504841493493'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/nib-method-to-return-nil-if-blank-in.html' title='nib Method to Return nil if blank? in Ruby'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8117601112955535099</id><published>2010-07-27T15:11:00.004-04:00</published><updated>2010-07-29T11:41:44.694-04:00</updated><title type='text'>Google's Server Error/Failure Page</title><content type='html'>Something I don't see very often...&lt;p/&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;a href="http://2.bp.blogspot.com/_dkSPoUrJq0E/TE8vPZsfqfI/AAAAAAAACNE/eet1f1fiFlc/s1600/google_fail.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_dkSPoUrJq0E/TE8vPZsfqfI/AAAAAAAACNE/eet1f1fiFlc/s320/google_fail.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Notice the inline styling and no use of graphics; it's self-contained as you'd expect.
&lt;pre&gt;&lt;code&gt;
&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;
&amp;lt;meta http-equiv="content-type" content="text/html;charset=utf-8"&amp;gt;
&amp;lt;title&amp;gt;502 Server Error&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;&amp;lt;!--
body {font-family: arial,sans-serif}
div.nav {margin-top: 1ex}
div.nav A {font-size: 10pt; font-family: arial,sans-serif}
span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}
div.nav A,span.big {font-size: 12pt; color: #0000cc}
div.nav A {font-size: 10pt; color: black}
A.l:link {color: #6f6f6f}
A.u:link {color: green}
//--&amp;gt;&amp;lt;/style&amp;gt;
&amp;lt;script&amp;gt;&amp;lt;!--
var rc=502;
//--&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body text=#000000 bgcolor=#ffffff&amp;gt;
&amp;lt;table border=0 cellpadding=2 cellspacing=0 width=100%&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td rowspan=3 width=1% nowrap&amp;gt;
&amp;lt;b&amp;gt;&amp;lt;font face=times color=#0039b6 size=10&amp;gt;G&amp;lt;/font&amp;gt;&amp;lt;font face=times color=#c41200 size=10&amp;gt;o&amp;lt;/font&amp;gt;&amp;lt;font face=times color=#f3c518 size=10&amp;gt;o&amp;lt;/font&amp;gt;&amp;lt;font face=times color=#0039b6 size=10&amp;gt;g&amp;lt;/font&amp;gt;&amp;lt;font face=times color=#30a72f size=10&amp;gt;l&amp;lt;/font&amp;gt;&amp;lt;font face=times color=#c41200 size=10&amp;gt;e&amp;lt;/font&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;/b&amp;gt;

&amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="#3366cc"&amp;gt;&amp;lt;font face=arial,sans-serif color="#ffffff"&amp;gt;&amp;lt;b&amp;gt;Error&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;
&amp;lt;blockquote&amp;gt;
&amp;lt;H1&amp;gt;Server Error&amp;lt;/H1&amp;gt;
The server encountered a temporary error and could not complete your request.&amp;lt;p&amp;gt;Please try again in 30 seconds.

&amp;lt;p&amp;gt;
&amp;lt;/blockquote&amp;gt;
&amp;lt;table width=100% cellpadding=0 cellspacing=0&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td bgcolor="#3366cc"&amp;gt;&amp;lt;img alt="" width=1 height=4&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8117601112955535099?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8117601112955535099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8117601112955535099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8117601112955535099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8117601112955535099'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/googles-server-errorfailure-page.html' title='Google&apos;s Server Error/Failure Page'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_dkSPoUrJq0E/TE8vPZsfqfI/AAAAAAAACNE/eet1f1fiFlc/s72-c/google_fail.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3799399420318085188</id><published>2010-07-07T16:25:00.002-04:00</published><updated>2010-07-12T16:18:24.384-04:00</updated><title type='text'>Ruby Operator Precedence</title><content type='html'>Ruby is about simplicity and clarity, but if you don't understand operator precedence, and think that "||" is the same as "or", it will eventually bite you.
&lt;p/&gt;
Take for example the case of an orange:
&lt;pre&gt;&lt;code&gt;
class Orange
 def sweet?
   true
 end

 def sour?
   false
 end
end
&lt;/code&gt;&lt;/pre&gt;
Very simple, right? You can do things such as:
&lt;pre&gt;&lt;code&gt;
orange = Orange.new
puts "This orange is sweet" if orange.sweet?
puts "This orange not sour" unless orange.sour?
&lt;/code&gt;&lt;/pre&gt;
But, lets try to make a method to test whether an orange is sweet or sour. 
&lt;pre&gt;&lt;code&gt;
def sweet_or_sour(orange)
 answer = orange.sour? or orange.sweet?
 puts "The orange is either sweet or sour: #{answer}"
end
&lt;/code&gt;&lt;/pre&gt;
Now call it:
&lt;pre&gt;&lt;code&gt;
orange = Orange.new
sweet_or_sour(orange)
&lt;/code&gt;&lt;/pre&gt;
What? The answer should be true! Why did this happen?
&lt;p/&gt;
The answer is that the "or" has lower precedence than the assignment operator "=". The same is true for "and" vs. "&amp;&amp;" ("and" has lower precedence than "="). "not" is also lower precedence than "=", but "not" is higher than "or" or "and".
&lt;p/&gt;
For more info, see &lt;a href="http://phrogz.net/programmingruby/language.html#table_18.4"&gt;Table 18.4&lt;/a&gt; of The Pragmatic Programmer's Guide to Programming Ruby.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3799399420318085188?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3799399420318085188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3799399420318085188' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3799399420318085188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3799399420318085188'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/ruby-operator-precedence.html' title='Ruby Operator Precedence'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4700216742143395831</id><published>2010-07-01T10:27:00.001-04:00</published><updated>2010-07-01T10:27:52.727-04:00</updated><title type='text'>The single-table inheritance mechanism failed to locate the subclass: 'regular'</title><content type='html'>If you get the following when trying to use ActiveRecord to view legacy tables in a database:&lt;br/&gt;
&lt;pre&gt;&lt;code&gt;
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:1667:in `instantiate': The single-table inheritance mechanism failed to locate the subclass: 'regular'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this column if you didn't intend it to be used for storing the inheritance class or overwrite NameOfYourModel.inheritance_column to use another column for that information. (ActiveRecord::SubclassNotFound)
&lt;/code&gt;&lt;/pre&gt;
Add this before your model definitions:&lt;br/&gt;
&lt;pre&gt;&lt;code&gt;
ActiveRecord::Base.inheritance_column = "activerecordtype"
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4700216742143395831?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4700216742143395831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4700216742143395831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4700216742143395831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4700216742143395831'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/how-to-fix-issue-single-table.html' title='The single-table inheritance mechanism failed to locate the subclass: &apos;regular&apos;'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2628262833654094274</id><published>2010-07-01T10:07:00.003-04:00</published><updated>2010-07-01T10:39:25.196-04:00</updated><title type='text'>Atlassian 20% Time and FedEx Day</title><content type='html'>This is a great presentation by Atlassian on their 20% Time:&lt;br/&gt;
* &lt;a href="http://www.atlassian.com/tv/episode?id=mb9r5rzmd2j4&amp;product=ide"&gt;Innovation@Atlassian: FedEx Day and 20% Time - Atlassian Summit: Charlie Talk&lt;/a&gt;&lt;br/&gt;
&lt;p/&gt;
Summary:
&lt;p/&gt;
Rules:
&lt;ul&gt;
&lt;li&gt;Is 20% of the development time that would have been spent, not support time, vacation, or conferences.
&lt;li&gt;Engineers should work on something at least related to the company, the company's products, or open-source components used by the company. (This doesn't need to be enforced very often.)
&lt;li&gt;To continue on the project and continue getting support: (This encourages projects to "fail early". But failure is not a problem. Innovation is about taking risks.)
&lt;ul&gt;
&lt;li&gt;If have worked on it 5 working days - must have 3 other engineers to say I think that is a good project and you should continue working on it. This is done via periodic reviews.
&lt;li&gt;If have worked on it 3 weeks - must have company founder's approval to continue working on it.
&lt;/ul&gt;
&lt;/ul&gt;
Scheduling:
&lt;ul&gt;
&lt;li&gt;Easier on larger teams (for example, a developer that wants to take off a week to work on something).
&lt;li&gt;Timekeeping - hard to get developers to do that. Someone just has to chase them with a whip.
&lt;/ul&gt;
Challenge:
&lt;ul&gt;
&lt;li&gt;Merging functionality with products, having to support life of project.
&lt;li&gt;It will affect schedule of products because of that, but is providing features.
&lt;/ul&gt;
Sorts of projects usually worked on (up to developer to decide):
&lt;ul&gt;
&lt;li&gt;Not big things.
&lt;li&gt;Things/bugs that annoy people.
&lt;/ul&gt;
More info and examples of things created with 20%:&lt;br/&gt;
&lt;a href="http://blogs.atlassian.com/developer/2008/03/20_time_experiment.html"&gt;Things tagged as "20 percent time" on Atlassian's developer blog&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2628262833654094274?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2628262833654094274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2628262833654094274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2628262833654094274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2628262833654094274'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/07/atlassian-20-time-and-fedex-day.html' title='Atlassian 20% Time and FedEx Day'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3116399085821194135</id><published>2010-06-24T13:27:00.000-04:00</published><updated>2010-06-24T13:27:51.464-04:00</updated><title type='text'>Fluid Textboxes with CSS</title><content type='html'>If you have a fluid layout, you probably want fluid textboxes also. You'd think it would just be the default these days, but it isn't.
&lt;pre&gt;&lt;code&gt;
textarea {
  resize:both;
  width:100%;
}
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3116399085821194135?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3116399085821194135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3116399085821194135' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3116399085821194135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3116399085821194135'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/fluid-textboxes-with-css.html' title='Fluid Textboxes with CSS'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1749402932637808016</id><published>2010-06-24T12:14:00.006-04:00</published><updated>2010-06-24T15:53:22.131-04:00</updated><title type='text'>Model to CSV in Rails</title><content type='html'>If you have to produce a report/CSV of data you're storing with Rails, you may eventually be required to create a CSV report of those model attributes in CSV format.
&lt;p/&gt;
A generic CSV implementation to convert an ActiveRecord model array to CSV may work at first:
&lt;pre&gt;&lt;code&gt;
require 'fastercsv'
...
def to_csv( records )
  csv_string = FasterCSV.generate do |csv|
    did_header = false      
    records.each do |record|
      unless did_header
        csv &amp;lt;&amp;lt; record.attribute_names.collect! {|attr_name| attr_name.titleize} 
        did_header = true
      end        
      values = []
      record.attribute_names.each do |attr_name|
        value = record[attr_name]
        value = value.join(', ') if value.respond_to?(:join)
        value = value.strftime('%Y-%m-%d') if value.respond_to?(:strftime)
        values.push value
      end
      csv &amp;lt;&amp;lt; values      
    end
  end
  csv_string
end
...
&lt;/code&gt;&lt;/pre&gt;
It would be great if something like that would suffice!
&lt;p/&gt;
But eventually, they may ask for something like the report columns being in the order they were gathered in and to include additional fields, etc. At this point, you may end up defining all of the fields (and possibly their headers) in arrays in one of your classes. Then you end up with something similar to:
&lt;code&gt;&lt;pre&gt;
require 'fastercsv'
...
def to_csv( records )
  csv_string = FasterCSV.generate do |csv|
    csv &lt;&lt; SomeModel.csv_headers
    records.each do |record|
      csv &lt;&lt; record.csv_data
    end
  end
  csv_string
end
...
&lt;/pre&gt;&lt;/code&gt;
And in the Model you may have something like:
&lt;pre&gt;&lt;code&gt;
def self.csv_headers
  [
    "Name",
    "Date",
    "Favorite Albums"
  ]
end

def csv_data
  [ 
    self.some_associated_model.try(:display_name),
    self.some_date.try(:strftime, '%m-%d-%Y'),
    self.some_array.try(:join, ', ')
  ]
end
&lt;/code&gt;&lt;/pre&gt;
Of course, you are probably going to be doing quite a bit of copying and pasting at this point, which is prone to error. I find it helpful to clean up the datasets using find/replace in a text editor and then compare side-by-side in Excel or a similar spreadsheet utility (sort by name on each column individually just to make sure you didn't miss any fields, etc.). If you have regexp functionality in an editor like TextMate, use it. It is a great time to hone your RegEx skills. For example, to convert some_attribute_name to "Some Attribute Name" may partially involve capitalizing each word after the other substitutions, which you can do via a find:
&lt;pre&gt;&lt;code&gt;
(\w+)
&lt;/code&gt;&lt;/pre&gt;
and replace with:
&lt;pre&gt;&lt;code&gt;
\u$1
&lt;/code&gt;&lt;/pre&gt;
then check "Regular Expression", then do Replace and Find until you have converted the set of labels. Then go back and make corrections (like changing "Us" to "US" and "By" to "by", etc.).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1749402932637808016?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1749402932637808016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1749402932637808016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1749402932637808016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1749402932637808016'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/model-to-csv-in-rails.html' title='Model to CSV in Rails'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6490259223933688764</id><published>2010-06-14T12:57:00.002-04:00</published><updated>2010-06-14T13:30:28.462-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git branch'/><title type='text'>Git Branch from Branch/Remote Branch and Making the New Branch Tracking Remote</title><content type='html'>It is an easy enough concept: You have a remote branch you created and you want to branch off of it into a new branch that is also remote and tracking. However, it was hard to find an example of this anywhere that contained all of the steps involved, so here they are. Thanks to Paul D. for his help and to Richard for support with this.
&lt;p/&gt;
Let's assume you already have a remote version branch and that your remote repo is "origin". Creating a branch off of master remotely and tracking it is described elsewhere, and I have a gbranch function in my &lt;a href="http://github.com/garysweaver/git-scripts"&gt;git-scripts&lt;/a&gt; project for that purpose. But what if you want to branch off of that remote branch?
&lt;p/&gt;
Ok, DON'T CHANGE THIS --no-track to -t/--track thinking you are smart. The goal here is to create a local copy of the remote 4.0 branch, not to create a local copy of it and track the remote existing branch. We'll add correct tracking in a minute!
&lt;pre&gt;&lt;code&gt;
git co --no-track -b new_branch_name origin/existing_remote_branch_to_branch_from
&lt;/code&gt;&lt;/pre&gt;
Now push that new branch to the remote repository:
&lt;pre&gt;&lt;code&gt;
git push origin new_branch_name
&lt;/code&gt;&lt;/pre&gt;
Finally, add tracking to the new_branch. If you have git 1.7.0 or later (do a git --version) then you can do this:
&lt;pre&gt;&lt;code&gt;
git branch --set-upstream new_branch_name origin/new_branch_name
&lt;/code&gt;&lt;/pre&gt;
If you don't have git 1.7.0 or later, you can edit .git/config and add something like:
&lt;pre&gt;&lt;code&gt;
[branch "new_branch_name"]
        remote = origin
        merge = refs/heads/new_branch_name
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6490259223933688764?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6490259223933688764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6490259223933688764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6490259223933688764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6490259223933688764'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/git-branch-from-branchremote-branch-and.html' title='Git Branch from Branch/Remote Branch and Making the New Branch Tracking Remote'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2757816387667192356</id><published>2010-06-09T15:23:00.011-04:00</published><updated>2010-06-10T16:15:50.505-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails ruby model activerecord html store multiple comma-delimited select dropdown single'/><title type='text'>Form with Multiple-selection Select Stored in Rails Comma-delimited Model Attribute</title><content type='html'>Here is an example for how you can do multiple-selections in a Rails form and store as a comma-delimited single field. This solution is based off of &lt;a href="http://www.designateonline.com/discussions/comments.php?DiscussionID=4537&amp;page=1"&gt;the one by smallbeer and Bill Posters&lt;/a&gt;, but in addition it sets the selections.
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;p&amp;gt;
  &amp;lt;script src=&amp;quot;http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;  
  &amp;lt;script&amp;gt;
$.noConflict();
 jQuery(document).ready(function($) {

  function setHandlers(e) {
   $('select[id^=select_favorite_foods]').change(updateValue);
  }

  function updateValue() {
   var select_values = [];
   $('select[id^=select_favorite_foods]').each(function(e) {
    if ($(this).val()) select_values.push($(this).val());
   });
   $('#name_of_your_model_favorite_foods').val(select_values.join(','));
  }
  
  function initSelection() {
    vals = $('#name_of_your_model_favorite_foods').val().split(',');
    var select_values = [];
    for ( i = 0; i &amp;lt; vals.length; i++) {
      if (vals[i]) select_values.push(vals[i]);
    }
    $('select[id^=select_favorite_foods]').val(select_values);
  }

  $(document).ready(function() {
   initSelection();
   setHandlers();
   updateValue(); 
  });
 });
  &amp;lt;/script&amp;gt;
  &amp;lt;%= f.label :favorite_foods, &amp;quot;Select your favorite foods:&amp;quot; %&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.hidden_field :favorite_foods %&amp;gt;
  &amp;lt;select id=&amp;quot;select_favorite_foods&amp;quot; multiple=&amp;quot;true&amp;quot; size=&amp;quot;3&amp;quot;&amp;gt;
    &amp;lt;option value=&amp;quot;Orange&amp;quot;&amp;gt;Orange&amp;lt;/option&amp;gt;
    &amp;lt;option value=&amp;quot;Banana&amp;quot;&amp;gt;Banana&amp;lt;/option&amp;gt;
    &amp;lt;option value=&amp;quot;Grapefruit&amp;quot;&amp;gt;Grapefruit&amp;lt;/option&amp;gt;
  &amp;lt;/select&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Messy, but it is just an example! However, for Rails, if you don't mind storing the value in the DB as YAML, that is a little easier. Also, this same technique with a few mods could work for any HTML form.
&lt;p/&gt;
&lt;em&gt;(Thanks to Jeremy who provided ideas when I was trying to work through the initSelection method.)&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2757816387667192356?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2757816387667192356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2757816387667192356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2757816387667192356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2757816387667192356'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/form-with-multiple-selection-select.html' title='Form with Multiple-selection Select Stored in Rails Comma-delimited Model Attribute'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5540645107582280032</id><published>2010-06-07T15:36:00.000-04:00</published><updated>2010-06-07T15:36:22.667-04:00</updated><title type='text'>Formatting Java in TextMate</title><content type='html'>If you need to reformat Java code in TextMate (in OS X), a simple way to do it is via:
&lt;pre&gt;&lt;code&gt;
command+a
opt+command+[
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
I have this note sitting on my desk as a reminder, so I thought it would be good to share. This is from Vinod in this &lt;a href="http://stackoverflow.com/questions/1633199/java-code-formatting-in-textmate"&gt;post on stack overflow&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5540645107582280032?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5540645107582280032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5540645107582280032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5540645107582280032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5540645107582280032'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/formatting-java-in-textmate.html' title='Formatting Java in TextMate'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2782004478930250911</id><published>2010-06-03T13:21:00.017-04:00</published><updated>2010-06-07T15:40:11.961-04:00</updated><title type='text'>Grammar Checking in OS X 10.6/Snow Leopard</title><content type='html'>There are so many features in OS X 10.6.3 that I like, but there is one that is extremely deficient: grammar checking. I would much rather have Mail.app correct my grammar mercilessly. Instead, it lets grammar pass that would make almost anyone with any knowledge of English grammar guffaw. (Sorry for using the word "guffaw". Guffawing is just something I imagine a grammarian would do.)
&lt;p/&gt;
Having something is sometimes better than nothing. For example, as noted in &lt;a href="http://www.innerexception.com/2008/10/tip-using-built-in-os-x-grammar-checker.html"&gt;a post that describes how to turn OS X grammar checking on&lt;/a&gt;, it knows "With regards to" is incorrect and has a tip that states "Is this an error for 'With regard to'? Try 'Concerning' or 'About' instead."
&lt;p/&gt;
However, the appearance that it is checking your grammar is misleading. If I type the following, "With regard to trees, I like apple yet than this is not a grammatically correct sentence come on please please please you need to at least notice some grammatical mistake here.", it checks out. Huh? If you want a real grammar checker in OS X, you might just buy &lt;a href="http://linguisoft.com/"&gt;Grammarian&lt;/a&gt; or a similar product.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2782004478930250911?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2782004478930250911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2782004478930250911' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2782004478930250911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2782004478930250911'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/06/grammar-check-in-os-x-1063-is-awful.html' title='Grammar Checking in OS X 10.6/Snow Leopard'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-898626228826510707</id><published>2010-05-21T16:18:00.002-04:00</published><updated>2010-06-10T09:41:47.140-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ojdbc driver debug logging log java database'/><title type='text'>How to Turn on Ojdbc Driver Debug Logging</title><content type='html'>It had been a while since I turned on ojdbc trace logging, so I had to look it up. Found a great article called &lt;a href="http://kualigan.blogspot.com/2010/04/turning-on-oracle-driver-tracing.html"&gt;Turning on Oracle Driver Tracing&lt;/a&gt; by Kualigan and added my notes below. I didn't use the Sun Java Logging API part of it.
&lt;p/&gt;
If you need to turn on &lt;a href="http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html"&gt;Oracle JDBC driver&lt;/a&gt; debug or trace logging, you first need to install the ojdbc driver "g" jar provided by Oracle (for example, ojdbc14_g.jar).
&lt;p/&gt;
If using Maven 2 and you don't want to make changes to your pom.xml(s), you could just swap out the version in your local repo with the debug version, but that may cause you later to accidentally include the debug version in another project, so I just changed the version in my pom.xml to a version I knew I didn't have called "9.2.0.8debug" (because I downloaded the ojdbc v9.2.0.8 debug driver).
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.oracle&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;ojdbc14&amp;lt;/artifactId&amp;gt;
            &amp;lt;!--&amp;lt;version&amp;gt;10.2.0.4.0&amp;lt;/version&amp;gt;--&amp;gt;
            &amp;lt;version&amp;gt;9.2.0.8debug&amp;lt;/version&amp;gt;
            &amp;lt;exclusions&amp;gt;
              &amp;lt;exclusion&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.tomcat&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;catalina&amp;lt;/artifactId&amp;gt;
              &amp;lt;/exclusion&amp;gt;
            &amp;lt;/exclusions&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then when I rebuilt, I used the command Maven 2 told me to use to manually install that jar.
&lt;pre&gt;&lt;code&gt;
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=9.2.0.8debug -Dpackaging=jar -Dfile=/Users/myuser/Downloads/ojdbc14_g.jar
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then if you are trying to trace in a functional test run by Maven, you modify pom.xml's surefire plugin config in its build plugins to turn on trace logging and specify a Java logging API config file:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;reportFormat&amp;gt;brief&amp;lt;/reportFormat&amp;gt;
                    &amp;lt;useFile&amp;gt;false&amp;lt;/useFile&amp;gt;
                    &amp;lt;systemProperties&amp;gt;
                        &amp;lt;property&amp;gt;
                            &amp;lt;name&amp;gt;oracle.jdbc.Trace&amp;lt;/name&amp;gt;
                            &amp;lt;value&amp;gt;true&amp;lt;/value&amp;gt;
                        &amp;lt;/property&amp;gt;
                    &amp;lt;/systemProperties&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
More info:&lt;br/&gt;
* &lt;a href="http://kualigan.blogspot.com/2010/04/turning-on-oracle-driver-tracing.html"&gt;Turning on Oracle Driver Tracing&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-898626228826510707?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/898626228826510707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=898626228826510707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/898626228826510707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/898626228826510707'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/how-to-turn-on-ojdbc-driver-debug.html' title='How to Turn on Ojdbc Driver Debug Logging'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4505432184117627413</id><published>2010-05-20T13:58:00.001-04:00</published><updated>2011-10-24T13:27:12.379-04:00</updated><title type='text'>Zip or War All Directories in Current Directory into Individual Zip or War Files</title><content type='html'>If you need to zip or war all of the directories only in the current directory into their own zip or war files, here are a few approaches: &lt;p/&gt;To zip all of the directories only in the current directory into individual zip files and retain the directory name in the zipped files so that when they expand they expand back into that directory, just use: &lt;p/&gt;&lt;pre&gt;&lt;code&gt;
find * -prune -type d -exec zip -r "{}.zip" "{}" \;
&lt;/code&gt;&lt;/pre&gt;But if you want to zip or war each so that you change directories (you change the current directory/working directory such that when the zip expands, it expands the files and directories of that directory into the current directory, as you would expect in a war file), you can't just use "cd" in the exec, and the unix zip command doesn't appear to let you change the working/current directory. The easiest thing to do is to have a separate shell script that changes the current working directory and does the zip. &lt;p/&gt;Create a file called warit.sh or zipit.sh and put it on the path. &lt;p/&gt;zipit.sh: &lt;pre&gt;&lt;code&gt;
#!/bin/bash
set -e
cd $1
zip -r "../$1.zip" .
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;warit.sh: &lt;pre&gt;&lt;code&gt;
#!/bin/bash
set -e
cd $1
jar cvf "../$1.war" .
&lt;/code&gt;&lt;/pre&gt;then just: &lt;pre&gt;&lt;code&gt;
find * -prune -type d -exec zipit.sh {} \;
&lt;/code&gt;&lt;/pre&gt;or &lt;pre&gt;&lt;code&gt;
find * -prune -type d -exec warit.sh {} \;
&lt;/code&gt;&lt;/pre&gt;and it will cd into each of the directories, zip all that up, and place the resulting zip or war into the parent directory. This is basically a hack for zip not taking an argument to specify the working directory, and because cd &lt;a href="http://www.unix.com/unix-dummies-questions-answers/23282-find-type-d-exec-cd.html"&gt;has difficulties running within find's exec&lt;/a&gt;. I fought this a good while and would appreciate if someone has a more elegant solution or could fight to allow the OS X 10.6.3 zip command to specify the current working directory.&lt;br /&gt;
&lt;p/&gt;Instead of "find * -prune -type d -exec ...", you can also use "find . -d 1 -type d -exec ...".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4505432184117627413?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4505432184117627413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4505432184117627413' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4505432184117627413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4505432184117627413'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/zip-or-war-all-directories-in-current.html' title='Zip or War All Directories in Current Directory into Individual Zip or War Files'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-5844630279900630061</id><published>2010-05-20T11:25:00.005-04:00</published><updated>2010-06-02T14:01:04.680-04:00</updated><title type='text'>Unplutofy Cleans web.xml and portlet*.tlds from Your Portlet Wars</title><content type='html'>Just wrote &lt;a href="http://github.com/garysweaver/unplutofy"&gt;Unplutofy&lt;/a&gt;, which includes an Ant task, Maven plugin, Command-line tool, and Java API to clean Apache Pluto additions to Portlet wars. What it does is fairly simple, but there wasn't anything in Pluto or uPortal that did this already.
&lt;p/&gt;
Why do this?
&lt;p/&gt;
Sometimes you may want to redeploy a portlet war that has already been deployed into a different version of a portal that has a different Pluto version. Since Pluto can be used (in uPortal via deployPortletApp, at least in past versions) to just tack on servlet and servlet-mapping tags to the web.xml without making sure that the old ones from past versions (or even current versions) are removed (see &lt;a href="https://issues.apache.org/jira/browse/PLUTO-576"&gt;PLUTO-576&lt;/a&gt;), it is helpful to know there is a way to revert the wars to the un-plutofied state.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-5844630279900630061?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/5844630279900630061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=5844630279900630061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5844630279900630061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/5844630279900630061'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/unplutofy-cleans-webxml-and-portlettlds.html' title='Unplutofy Cleans web.xml and portlet*.tlds from Your Portlet Wars'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4109290893369434209</id><published>2010-05-18T09:15:00.001-04:00</published><updated>2010-05-18T09:18:05.968-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os_x git gitx'/><title type='text'>View and Graph Git Repositories in OS X</title><content type='html'>&lt;a href="http://www.blogger.com/post-create.g?blogID=7557194597309413467"&gt;GitX&lt;/a&gt; is a great tool for visualizing git repositories in Mac OS X. Just unzip the app, drag it into your Applications, start it, and got to GitX menu -&amp;gt; Enable Terminal Usage... That will put it into your bin directory so that you can just type:
&lt;pre&gt;&lt;code&gt;
gitx
&lt;/code&gt;&lt;/pre&gt;
while in a git repo directory, and it will popup with a visual graph of the repository.
&lt;p/&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_dkSPoUrJq0E/S_KS5OVoA6I/AAAAAAAABX0/QZbzCTBREkg/s1600/gitx_screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/_dkSPoUrJq0E/S_KS5OVoA6I/AAAAAAAABX0/QZbzCTBREkg/s640/gitx_screenshot.png" width="627" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p/&gt;
Pretty neat, and pretty slick, too!
&lt;p/&gt;
For more info, see:&lt;br/&gt;
* &lt;a href="http://www.gitready.com/intermediate/2009/01/13/visualizing-your-repo.html"&gt;http://www.gitready.com/intermediate/2009/01/13/visualizing-your-repo.html&lt;/a&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4109290893369434209?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4109290893369434209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4109290893369434209' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4109290893369434209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4109290893369434209'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/view-and-graph-git-repositories-in-os-x.html' title='View and Graph Git Repositories in OS X'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_dkSPoUrJq0E/S_KS5OVoA6I/AAAAAAAABX0/QZbzCTBREkg/s72-c/gitx_screenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3034407683546309798</id><published>2010-05-14T14:04:00.011-04:00</published><updated>2010-12-22T13:31:35.185-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shib shibboleth shibbolize uportal login auth authn authorization'/><title type='text'>How to Shibbolize uPortal 3.2.1</title><content type='html'>This assumes you've already setup the Java 6 SDK, uPortal 3.2.1, Shibboleth, and know that Shibboleth is sending the username to Tomcat via a REMOTE_USER header. It also assumes you have added the tomcatAuthentication="false" to all relevant connectors in Tomcat 6's server.xml. For assistance with these tasks, go to the &lt;a href="http://shibboleth.internet2.edu/lists.html"&gt;official site&lt;/a&gt; and the &lt;a href="http://shibboleth.internet2.edu/lists.html"&gt;shibboleth-users mailing list&lt;/a&gt;. &lt;p/&gt;Before you start, you'll probably want to add an admin user with the same ID as that which will come through via REMOTE_USER from Shibboleth. If you don't, you can just change "admin" to your username in UP_USER.USER_NAME, UP_PERSON_DIR.USER_NAME, and in UP_GROUP_MEMBERSHIP.MEMBER_KEY. &lt;p/&gt;After doing all that, here is one way to Shibbolize uPortal v3.2.1. This assumes you don't need any authN except Shibboleth: &lt;p/&gt;Edit WEB-INF/classes/layout/theme/universality/components.xsl &lt;pre&gt;&lt;code&gt;
 &amp;lt;xsl:template name=&amp;quot;login&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;portalLogin&amp;quot; class=&amp;quot;fl-widget&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;fl-widget-inner&amp;quot;&amp;gt;
        &amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;Login&amp;quot;&amp;gt;
            &amp;lt;fieldset id=&amp;quot;portalLogin&amp;quot;&amp;gt;
                &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;input class=&amp;quot;uportal-button&amp;quot; name=&amp;quot;Login&amp;quot; value=&amp;quot;Login&amp;quot; type=&amp;quot;submit&amp;quot; /&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;
                &amp;lt;xsl:apply-templates/&amp;gt;
            &amp;lt;/fieldset&amp;gt;
        &amp;lt;/form&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;                             
  &amp;lt;/xsl:template&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;This assumes that you have configured Shibboleth to guard Login under uPortal (example: https://employees.acme.com/uPortal/Login). It also assumes you are using that theme. For mobile support, make a similar change to WEB-INF/classes/layout/theme/muniversality/components.xsl. &lt;p/&gt;I also modified WEB-INF/classes/org/jasig/portal/channels/CLogin/html.xsl with the following. This is the template for local login and it shouldn't be used if you make the change above. &lt;pre&gt;&lt;code&gt;
   &amp;lt;xsl:template match=&amp;quot;login-status&amp;quot;&amp;gt;
        &amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;Login&amp;quot;&amp;gt;
            &amp;lt;fieldset id=&amp;quot;portalLogin&amp;quot;&amp;gt;
                &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;input class=&amp;quot;uportal-button&amp;quot; name=&amp;quot;Login&amp;quot; value=&amp;quot;Login&amp;quot; type=&amp;quot;submit&amp;quot; /&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;
                &amp;lt;xsl:apply-templates/&amp;gt;
            &amp;lt;/fieldset&amp;gt;
        &amp;lt;/form&amp;gt;  
    &amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;Edit WEB-INF/classes/properties/contexts/userContext.xml &lt;pre&gt;&lt;code&gt;
&amp;lt;!--&amp;lt;bean id=&amp;quot;personManager&amp;quot; class=&amp;quot;org.jasig.portal.security.provider.SimplePersonManager&amp;quot;/&amp;gt; --&amp;gt;
&amp;lt;bean id=&amp;quot;personManager&amp;quot; class=&amp;quot;org.jasig.portal.security.provider.RemoteUserPersonManager&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;Edit WEB-INF/classes/properties/security.properties &lt;pre&gt;&lt;code&gt;
## This is the factory that supplies the concrete authentication class
root=org.jasig.portal.security.provider.UnionSecurityContextFactory
root.remoteuser=org.jasig.portal.security.provider.RemoteUserSecurityContextFactory
#root.cas=org.jasig.portal.security.provider.cas.CasAssertionSecurityContextFactory
#root.simple=org.jasig.portal.security.provider.SimpleSecurityContextFactory

...

## Answers where the user will be redirected when log out occurs. Each security context can have one.
## (See comments in the LogoutServlet class)
## It would be better to escape the value of the url parameter, but since there are no parameters on the
## unescaped URL and since there are no further parameters on the logout URL, this does work.
#logoutRedirect.root=http://localhost:8080/cas/logout?url=http://localhost:8080/uPortal/Login
logoutRedirect.root=/Shibboleth.sso/Logout
&lt;/code&gt;&lt;/pre&gt;&lt;p/&gt;There is a better way of doing this that would allow it to be an option along with local login and CAS, and I offered to provide such a patch to uPortal, but there didn't seem to be any interest, so I didn't spend additional time on it.&lt;p/&gt;See also:&lt;br /&gt;
* &lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Shibbing+uPortal+JA-SIG+Session"&gt;https://spaces.internet2.edu/display/ShibuPortal/Shibbing+uPortal+JA-SIG+Session&lt;/a&gt;&lt;br /&gt;
* &lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Home"&gt;https://spaces.internet2.edu/display/ShibuPortal/Home&lt;/a&gt;&lt;br /&gt;
* &lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Portal+Design"&gt;https://spaces.internet2.edu/display/ShibuPortal/Portal+Design&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3034407683546309798?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3034407683546309798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3034407683546309798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3034407683546309798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3034407683546309798'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/how-to-shibbolize-uportal-321.html' title='How to Shibbolize uPortal 3.2.1'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-844458957236347338</id><published>2010-05-03T16:23:00.007-04:00</published><updated>2010-05-03T16:46:00.242-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby Net::HTTP use_ssl'/><title type='text'>How to Fix Net::HTTPBadResponse: wrong status line: "&lt;!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"&gt;" in Ruby</title><content type='html'>Using Ruby 1.8.7:
&lt;pre&gt;&lt;code&gt;
$ ruby -version
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0
&lt;/code&gt;&lt;/pre&gt;

If I do the following, you can see where it might be confusing that the error has nothing to do with me not specifying that I wanted to use HTTPS vs HTTP:
&lt;pre&gt;&lt;code&gt;
$ irb
&amp;gt;&amp;gt; require 'net/http'
=&amp;gt; true
&amp;gt;&amp;gt; Net::HTTP.get_response(URI.parse('http://www.google.com/'))
=&amp;gt; #&amp;lt;Net::HTTPOK 200 OK readbody=true&amp;gt;
&amp;gt;&amp;gt; Net::HTTP.get_response(URI.parse('https://www.verisign.com/'))
Net::HTTPBadResponse: wrong status line: &amp;quot;&amp;lt;!DOCTYPE HTML PUBLIC \&amp;quot;-//IETF//DTD HTML 2.0//EN\&amp;quot;&amp;gt;&amp;quot;
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:2022:in `read_status_line'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:2009:in `read_new'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:1050:in `request'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:948:in `request_get'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:380:in `get_response'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:543:in `start'
 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:379:in `get_response'
 from (irb):3
&lt;/code&gt;&lt;/pre&gt;

But if I change the code to specify I want to use HTTPS:
&lt;pre&gt;&lt;code&gt;
$ irb
&amp;gt;&amp;gt; require 'net/http'
=&amp;gt; true
&amp;gt;&amp;gt; require 'net/https'
=&amp;gt; true
&amp;gt;&amp;gt; url = URI.parse('https://www.verisign.com/')
=&amp;gt; #&amp;lt;URI::HTTPS:0x101200588 URL:https://www.verisign.com/&amp;gt;
&amp;gt;&amp;gt; http = Net::HTTP.new(url.host, url.port)
=&amp;gt; #&amp;lt;Net::HTTP www.verisign.com:443 open=false&amp;gt;
&amp;gt;&amp;gt; http.use_ssl = true
=&amp;gt; true
&amp;gt;&amp;gt; request = Net::HTTP::Get.new(url.path)
=&amp;gt; #&amp;lt;Net::HTTP::Get GET&amp;gt;
&amp;gt;&amp;gt; response = http.start {|http| http.request(request) }
warning: peer certificate won't be verified in this SSL session
=&amp;gt; #&amp;lt;Net::HTTPOK 200 OK readbody=true&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

all is good!
&lt;p/&gt;
This came about because an example for an HTTP GET in the Ruby standard documentation doesn't mention HTTPS, and it is only natural that at some point you'll try to use that same code to get something via SSL/HTTPS, and it will fail with a similar error to the above.
&lt;p/&gt;
Here is an imperfect generic implementation of GET utility method based on the original:
&lt;pre&gt;&lt;code&gt;
  # copied from http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html then modified to support SSL
  def self.fetch(uri_str, limit = 10)
    # You should choose better exception.
    raise ArgumentError, 'HTTP redirect too deep' if limit == 0
    
    url = URI.parse(uri_str)      
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = (url.scheme == 'https')
    request = Net::HTTP::Get.new(url.path)
    response = http.start {|http| http.request(request) }
      
    case response
    when Net::HTTPSuccess     then response
    when Net::HTTPRedirection then fetch(response['location'], limit - 1)
    else
      response.error!
    end
  end
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-844458957236347338?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/844458957236347338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=844458957236347338' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/844458957236347338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/844458957236347338'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/how-to-fix-nethttpbadresponse-wrong.html' title='How to Fix Net::HTTPBadResponse: wrong status line: &amp;quot;&amp;lt;!DOCTYPE HTML PUBLIC \&amp;quot;-//IETF//DTD HTML 2.0//EN\&amp;quot;&amp;gt;&amp;quot; in Ruby'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7845180288351013271</id><published>2010-05-03T09:26:00.017-04:00</published><updated>2010-05-05T10:17:20.409-04:00</updated><title type='text'>OS X 10.6.2/Snow Leopard Login Issues</title><content type='html'>I tried to login to OS X 10.6.2/Snow Leopard multiple times this morning into the black background login from the screensaver and got rejected every time. I rebooted, then had to login both in the main boot login screen and the black login screen. I usually would only have to login once via the main boot login after a restart.
&lt;p/&gt;
If you have this trouble also, I suggest holding down the power button until the Mac goes off, press it again after it is off to start it back up, then login (as many times as necessary) to get in.
&lt;p/&gt;
My first thought was that it was a virus/trojan/worm/some kind of malware, or I got hacked. I'm still not ruling those out, but it is suspicious that others on Twitter are reporting similar issues. Wondering if it is related to a recent update from Apple?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7845180288351013271?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7845180288351013271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7845180288351013271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7845180288351013271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7845180288351013271'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/05/snow-leopard-os-x-login-issues.html' title='OS X 10.6.2/Snow Leopard Login Issues'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7628172778338890394</id><published>2010-04-29T12:21:00.016-04:00</published><updated>2010-04-29T13:26:01.493-04:00</updated><title type='text'>Getting Maven to Work in Hudson</title><content type='html'>We were having some trouble today getting a Maven 2 project to build in Hudson v1.353. Specifically, we were getting an 'Exception in thread "main" java.net.ConnectException: Connection refused'.
&lt;p/&gt;
We added:
&lt;pre&gt;&lt;code&gt;
-Djava.awt.headless=true
&lt;/code&gt;&lt;/pre&gt;
to MAVEN_OPTS in the hudson configuration page (per Martijn Dashorst and mbrictson's &lt;a href="http://hudson.361315.n4.nabble.com/Maven-jobs-fail-upon-upgrade-to-1-341-Can-t-connect-to-window-server-td1288967.html"&gt;posts&lt;/a&gt;) and this issue seems to have gone away. Thanks much to Martijn and mbrictson for sharing this solution!
&lt;p/&gt;
It is strange that after setting this and then removing it, projects continue to build correctly, even if MAVEN_OPTS in each individual project (in Advanced under Build section of your projects Configure page in Hudson) does not contain this parameter. It also continued to work after Hudson was restarted.
&lt;p/&gt;
Note: I had previously installed Maven to a local spot manually instead of via Hudson. I tried to let Hudson automatically install it, but it had some wierd errors on build. First I had some rights-related issues that I fixed, but then I ran into a &lt;a href="http://issues.hudson-ci.org/browse/HUDSON-3273"&gt;SocketTimeoutException&lt;/a&gt; and just decided install Maven 2 myself in different directory than where Hudson puts it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7628172778338890394?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7628172778338890394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7628172778338890394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7628172778338890394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7628172778338890394'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/getting-maven-to-work-in-hudson.html' title='Getting Maven to Work in Hudson'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2829690748120394883</id><published>2010-04-28T15:45:00.002-04:00</published><updated>2010-04-28T16:43:40.447-04:00</updated><title type='text'>Bad Existing Git Repo Causes Subsequent Svn to Git Conversion Error</title><content type='html'>If you get the following error:
&lt;pre&gt;&lt;code&gt;
$ git svn clone svn+ssh://userid@some.host/path/to/svn/project/dir --no-metadata -T trunk /path/to/local/git/repo/project/dir
W: Ignoring error from SVN, path probably does not exist: (160013): Filesystem has no item: File not found: revision 8481, path 'misspelled/or/invalid/path/to/svn/project/dir'
W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.
This may take a while on large repositories
&lt;/code&gt;&lt;/pre&gt;
try removing the directory of the git repo that you are trying to migrate into from svn, or just move it out of the way:
&lt;pre&gt;&lt;code&gt;
mv /path/to/local/git/repo/project/dir /path/to/local/git/repo/project/dir.bak
&lt;/code&gt;&lt;/pre&gt;
It doesn't appear to like having a poorly migrated git repo already there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2829690748120394883?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2829690748120394883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2829690748120394883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2829690748120394883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2829690748120394883'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/bad-existing-git-repo-causes-subsequent.html' title='Bad Existing Git Repo Causes Subsequent Svn to Git Conversion Error'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3773289345654607024</id><published>2010-04-28T15:14:00.007-04:00</published><updated>2010-04-28T15:43:39.589-04:00</updated><title type='text'>Misspelled Hostname in SVN URL Causes Wierd Error When Converting Subversion to Git</title><content type='html'>Got the following error when trying to convert an svn project to a git repo:
&lt;pre&gt;&lt;code&gt;
$ git svn clone svn+ssh://userid@some.host/path/to/svn/project/dir --no-metadata -T trunk /path/to/local/git/repo/project/dir
Use of uninitialized value in concatenation (.) or string at /opt/local/lib/perl5/vendor_perl/5.8.9/darwin-2level/SVN/Core.pm line 584.
Network connection closed unexpectedly:  at /opt/local/libexec/git-core/git-svn line 1888
&lt;/code&gt;&lt;/pre&gt;
I determined that the host name in the svn URL was incorrect. The "Use of uninitialized value in concatenation (.) or string at /opt/local/lib/perl5/vendor_perl/5.8.9/darwin-2level/SVN/Core.pm line 584." didn't help much. The hint here was "Network connection closed unexpectedly" after which I just happened to notice the bad hostname. Actually, I think it was a bad character inserted because I copied/pasted of a number of commands at once into terminal.app, which tends to cause issues. Hope this helps someone else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3773289345654607024?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3773289345654607024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3773289345654607024' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3773289345654607024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3773289345654607024'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/misspelled-hostname-in-svn-url-causes.html' title='Misspelled Hostname in SVN URL Causes Wierd Error When Converting Subversion to Git'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6415741911677500657</id><published>2010-04-27T10:50:00.017-04:00</published><updated>2010-04-27T14:33:40.880-04:00</updated><title type='text'>TextMate Slowness with Ruby on Rails Language Grammar</title><content type='html'>When editing an erb file, I noticed that when I escaped most of the EOL chars with &amp;lt;%# and put %&gt; at beginning of the following lines, TextMate 1.5.9 (build 1510) got really slow; the beach ball just kept spinning and spinning in OS X 10.6.2 Snow Leopard, and it appeared to be locked-up/frozen/non-responsive.
&lt;p/&gt;
I ended up fixing this by changing the language grammar at the bottom of the TextMate window to "HTML" instead of "Ruby on Rails" for .erb files.
&lt;p/&gt;
Note: something else to look into when TextMate is slow is the number of files in the projects you have open. Try closing projects or reducing the number of files in the project if things are slow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6415741911677500657?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6415741911677500657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6415741911677500657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6415741911677500657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6415741911677500657'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/textmate-slowness-with-ruby-on-rails.html' title='TextMate Slowness with Ruby on Rails Language Grammar'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6376253166510923640</id><published>2010-04-26T13:55:00.026-04:00</published><updated>2010-04-28T15:12:09.817-04:00</updated><title type='text'>Modular Design vs. MVC</title><content type='html'>Usually the implementation of the View in MVC is something that is so geared towards presentation or the final display of the data that reuse by other components (those not interested in the presentation, but only interested in the data produced for the presentation) are not considered.
&lt;p/&gt;
Think of just about any standard framework used to help implement the view for a web application in any programming language. Do you have an easy way to just call that code from the controller and get its response for reuse somewhere else in the application? Probably not. So, why would you want to?
&lt;p/&gt;
In an Rails app + XML/JSON/JSONP service that we had developed, the first version of the app/service did the XML/JSON/JSONP generation outside of the view code. For example, the to_xml implementation was just another method, so it would have been simple enough to reuse it almost anywhere within the app.
&lt;p/&gt;
However, in the second version of the app/service, this was changed so that there was a view to generate the XML. Considering XML to be a view just like anything else seems at first to a good idea. But it makes it more complex now to do the equivalent of to_xml if you need it elsewhere in the app. This seems to have somewhat sacrificed Modular Design for the traditional push of presentation-related code into the view layer.
&lt;p/&gt;
MVC would at first appear just to be a subset of Modular Design. But the problem is that when you say (just as an example), "This functionality is just for the view, so I don't really care if you want to use it for anything else, because my job is just to provide the last step prior to presentation," you are probably sacrificing some degree of modularity and potential reuse.
&lt;p/&gt;
For webapps, there are obvious benefits for using MVC, and odds are the framework you are using promotes MVC. However, it makes sense to at least consider Modular Design principles when coding bits of functionality that could be reused.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6376253166510923640?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6376253166510923640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6376253166510923640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6376253166510923640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6376253166510923640'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/modular-design-vs-mvc.html' title='Modular Design vs. MVC'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3216773080740708222</id><published>2010-04-23T13:08:00.003-04:00</published><updated>2010-04-23T13:37:41.850-04:00</updated><title type='text'>git-core +svn MacPorts Install in Snow Leopard</title><content type='html'>Paul Downman has a &lt;a href="http://pauldowman.com/2008/07/26/how-to-convert-from-subversion-to-git/"&gt;great article&lt;/a&gt; on converting svn to git repositories, but upon trying to run the first command in OS X 10.6.2:
&lt;pre&gt;&lt;code&gt;
sudo port install git-core +svn
&lt;/code&gt;&lt;/pre&gt;
I got:
&lt;pre&gt;&lt;code&gt;
...
---&amp;gt;  Building cyrus-sasl2
Error: Target org.macports.build returned: shell command &amp;quot; cd &amp;quot;/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_security_cyrus-sasl2/work/cyrus-sasl-2.1.23&amp;quot; &amp;amp;&amp;amp; /usr/bin/make -j3 all &amp;quot; returned error 2
Command output:  fi
if /bin/sh ../libtool --mode=compile /usr/bin/gcc-4.2 -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../include   -I/opt/local/include -I/opt/local/include  -Wall -W -O2 -arch x86_64 -MT db_ndbm.lo -MD -MP -MF &amp;quot;.deps/db_ndbm.Tpo&amp;quot; \
   -c -o db_ndbm.lo `test -f 'db_ndbm.c' || echo './'`db_ndbm.c; \
 then mv -f &amp;quot;.deps/db_ndbm.Tpo&amp;quot; &amp;quot;.deps/db_ndbm.Plo&amp;quot;; \
 else rm -f &amp;quot;.deps/db_ndbm.Tpo&amp;quot;; exit 1; \
 fi
if /usr/bin/gcc-4.2 -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../include   -I/opt/local/include -I/opt/local/include  -Wall -W -O2 -arch x86_64 -MT db_ndbm.o -MD -MP -MF &amp;quot;.deps/db_ndbm.Tpo&amp;quot; \
   -c -o db_ndbm.o `test -f 'db_ndbm.c' || echo './'`db_ndbm.c; \
 then mv -f &amp;quot;.deps/db_ndbm.Tpo&amp;quot; &amp;quot;.deps/db_ndbm.Po&amp;quot;; \
 else rm -f &amp;quot;.deps/db_ndbm.Tpo&amp;quot;; exit 1; \
 fi
if /usr/bin/gcc-4.2 -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../include   -I/opt/local/include -I/opt/local/include  -Wall -W -O2 -arch x86_64 -MT allockey.o -MD -MP -MF &amp;quot;.deps/allockey.Tpo&amp;quot; \
   -c -o allockey.o `test -f 'allockey.c' || echo './'`allockey.c; \
 then mv -f &amp;quot;.deps/allockey.Tpo&amp;quot; &amp;quot;.deps/allockey.Po&amp;quot;; \
 else rm -f &amp;quot;.deps/allockey.Tpo&amp;quot;; exit 1; \
 fi
/usr/bin/gcc-4.2 -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../include -I/opt/local/include -I/opt/local/include -Wall -W -O2 -arch x86_64 -MT allockey.lo -MD -MP -MF .deps/allockey.Tpo -c allockey.c  -fno-common -DPIC -o allockey.lo
/usr/bin/gcc-4.2 -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../include -I/opt/local/include -I/opt/local/include -Wall -W -O2 -arch x86_64 -MT db_ndbm.lo -MD -MP -MF .deps/db_ndbm.Tpo -c db_ndbm.c  -fno-common -DPIC -o db_ndbm.lo
allockey.c: In function '_sasldb_putsecret':
allockey.c:191: warning: pointer targets in passing argument 6 of '_sasldb_putdata' differ in signedness
allockey.c: In function '__sasldb_internal_list':
allockey.c:197: warning: unused parameter 'rock'
allockey.c: In function '_sasldb_putsecret':
allockey.c:191: warning: pointer targets in passing argument 6 of '_sasldb_putdata' differ in signedness
allockey.c: In function '__sasldb_internal_list':
allockey.c:197: warning: unused parameter 'rock'
mv: rename .deps/allockey.Tpo to .deps/allockey.Plo: No such file or directory
make[2]: *** [allockey.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

Error: The following dependencies failed to build: p5-svn-simple subversion-perlbindings cyrus-sasl2 neon serf subversion p5-term-readkey
Error: Status 1 encountered during processing.
Before reporting a bug, first run the command again with the -d flag to get complete output.
&lt;/code&gt;&lt;/pre&gt;
After getting this I first tried to clean the dependencies that failed to build:
&lt;pre&gt;&lt;code&gt;
sudo port clean p5-svn-simple subversion-perlbindings cyrus-sasl2 neon serf subversion p5-term-readkey
&lt;/code&gt;&lt;/pre&gt;
and then did "sudo port install git-core +svn" again, and it failed. Following a lead on &lt;a href="http://lists.macosforge.org/pipermail/macports-users/2010-January/018314.html"&gt;something else I saw&lt;/a&gt;, I tried:
&lt;pre&gt;&lt;code&gt;
sudo port install cyrus-sasl2 +universal
&lt;/code&gt;&lt;/pre&gt;
and got:
&lt;pre&gt;&lt;code&gt;
---&amp;gt;  Computing dependencies for cyrus-sasl2
---&amp;gt;  Fetching cyrus-sasl2
---&amp;gt;  Verifying checksum(s) for cyrus-sasl2
---&amp;gt;  Extracting cyrus-sasl2
---&amp;gt;  Applying patches to cyrus-sasl2
---&amp;gt;  Configuring cyrus-sasl2
Error: You cannot install cyrus-sasl2 for the architecture(s) x86_64 i386 because
Error: its dependency openssl only contains the architecture(s) x86_64.
Error: 
Error: Try rebuilding openssl (and all its dependencies) with
Error: the +universal variant by running
Error: 
Error:     sudo port upgrade --enforce-variants openssl +universal
Error: 
Error: Target org.macports.configure returned: incompatible architectures in dependencies
Error: Status 1 encountered during processing.
Before reporting a bug, first run the command again with the -d flag to get complete output.
&lt;/code&gt;&lt;/pre&gt;
So then I did:
&lt;pre&gt;&lt;code&gt;
sudo port upgrade --enforce-variants openssl +universal
sudo port install cyrus-sasl2 +universal
sudo port install git-core +svn
&lt;/code&gt;&lt;/pre&gt;
and it installed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3216773080740708222?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3216773080740708222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3216773080740708222' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3216773080740708222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3216773080740708222'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/git-core-svn-macports-install-in-snow.html' title='git-core +svn MacPorts Install in Snow Leopard'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-427504513069976573</id><published>2010-04-15T09:43:00.019-04:00</published><updated>2010-04-15T10:24:47.762-04:00</updated><title type='text'>Nil Model Attributes and Lazy-loading</title><content type='html'>I was working on a project where there was a method in a model that I defined with references to ActiveRecord model attributes like @attribute_name instead of via the accessors like self.attribute_name.
&lt;p/&gt;
In one route and in one controller, a method checking @attribute_name would return the desired instance of the object. In another route and another controller, it would return nil, even though that attribute was not nil when accessed by its views.
&lt;p/&gt;
Paul D. mentioned that I should try using an accessor instead of direct attribute reference, and, sure enough, this issue was caused by trying to access an attribute directly that ActiveRecord would have lazy-loaded when retrieved via accessor.
&lt;p/&gt;
As Paul said, unless the attributes you are working with are ones that you created instead of ActiveRecord's, it is a better idea to use the accessors in your models.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-427504513069976573?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/427504513069976573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=427504513069976573' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/427504513069976573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/427504513069976573'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/nil-model-attributes-and-lazy-loading.html' title='Nil Model Attributes and Lazy-loading'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6270581980148032275</id><published>2010-04-09T12:03:00.013-04:00</published><updated>2010-04-09T13:26:49.941-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cms vcs'/><title type='text'>Push CMSs and Version Control</title><content type='html'>If you are choosing a CMS, you may want to look into whether it gives you a clean and obvious way to view differences between the managed content and the published/served content. This is not often a straightforward task. In fact, some CMSs have features that make this a nearly impossible task, because the content you view in the CMS does not have a 1:1 relationship with the published files in the case of a push CMS (possibly because there are transforms during the publish, etc.). Having audit history of changes made just within the CMS or just being able to view changes between versions of content in the CMS might be nice, but if it doesn't take into account what was actually published or is still viewable by the user or another application, those alone may not be sufficient.
&lt;p/&gt;
A few examples of things that could go wrong if you don't have a good handle on what resides in the publish destination:
&lt;ul&gt;
&lt;li&gt;Users and applications can continue to access old content via deep-links.&lt;/li&gt;
&lt;li&gt;You might not be aware of content that was corrupted on/after publish or was only partially-published.&lt;/li&gt;
&lt;/ul&gt;
For this reason, I'm a much bigger fan these days of the concept of a pull CMS (a CMS that serves content) as they seem to do a better job with &lt;a href="http://en.wikipedia.org/wiki/WYSIWYG"&gt;"What you see is what you get"&lt;/a&gt;. Caching and copying static rendered content from a pull CMS (a CMS that serves content) seems enough for most of the needs we'd have, even if it doesn't solve every problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6270581980148032275?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6270581980148032275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6270581980148032275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6270581980148032275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6270581980148032275'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/push-cms-and-version-control.html' title='Push CMSs and Version Control'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8672067279428112766</id><published>2010-04-08T07:51:00.015-04:00</published><updated>2010-04-08T08:19:44.371-04:00</updated><title type='text'>Change sed's Pattern Delimiter Character</title><content type='html'>sed has a neat feature as &lt;a href="http://forums.devshed.com/unix-help-35/sed-not-escaping-forward-slash-393115.html"&gt;noted&lt;/a&gt; by mu where you can use any character to delimit the parts of the regular expression, which means you can control what characters would have to be escaped in your patterns.
&lt;p/&gt;
Instead of using the normal forward-slash, you can use a pipe (|) or any character other than a backslash or newline character. Note that putting a backslash character before the delimiting character causes the character to be treated literally within the expression rather than as a delimiter.
&lt;p/&gt;
For example, to replace all instances (because of the g) of the text "http://www.example.com/some/old/path" in old_file with "http://acme.com/some/new/path" and output to new_file, use:
&lt;pre&gt;&lt;code&gt;
sed -e 's|http://www.example.com/some/old/path|http://acme.com/some/new/path|g' old_file &amp;gt; new_file
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8672067279428112766?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8672067279428112766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8672067279428112766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8672067279428112766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8672067279428112766'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/change-seds-pattern-delimiter-character.html' title='Change sed&apos;s Pattern Delimiter Character'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8113726953657435340</id><published>2010-04-06T06:08:00.006-04:00</published><updated>2010-04-06T12:56:51.039-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cross-comain portlet iframe'/><title type='text'>Gotchas for Cross-domain Portlets via iFrames</title><content type='html'>We explored the available (Google-able) cross-domain iframe solutions a few months ago to see if using iFrames for cross-domain apps we would want to run as portlets would be a good idea. But the problem is that in most cross-domain hacks the iframed webapp must initiate the resizing of its parent container via changing its target link. You can imagine how that would cause some issues:
&lt;ol&gt;
&lt;li&gt;The app you are trying to portlet-ize should not care whether it is in a portlet or not.&lt;/l1&gt;
&lt;li&gt;The app you are trying to portlet-ize should not have to do the resizing, because that requires that all actions in the app that could affect its size need to call the refresh methods that set the URL target of themselves that the parent is watching in order to relay the new height and/or width.&lt;/li&gt;
&lt;/ol&gt;
This isn't to say that iFrames won't work in portals. For example, I know that John King of Geneseo U. uses iFrames in their portal but they own all of the portlet-ed apps and they are all on the same domain. However, for those exploring cross-domain iframed webapps in their portal, be aware of these gotchas.
&lt;p/&gt;
If you want to develop apps that would be hosted in a different domain than the portal, you might look into Jasig's WebProxyPortlet (to proxy the external app), rails-portlet (if developing Rails apps), portletbridge, Grails Portlets Plugin (if developing Grails apps), etc. Also, we're working on an idea in-house at the moment that involves a completely client-side based javascript/jQuery solution using jsonp to communicate with cross-domain services. Jeremy B. is doing the heavy-lifting with the jQuery UI and JSON usage and following that, I'm hoping to make a gem to handle the creation of that javascript/HTML- that way it will serve up the client-side code after which jsonp is used solely for additional actions.
&lt;p/&gt;
However, if you don't have control over the external app you want to show up in the portal, then Jasig's WebProxyPortlet or Mikael Lammentausa's html2jsr286 might be options.
&lt;p/&gt;
Hope this helps someone else.
&lt;p/&gt;
See also:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogger-mikael.blogspot.com/2010/04/comparison-of-web-proxy-portlet.html"&gt;Comparison of Web Proxy Portlet, Portletbridge and html2jsr286&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8113726953657435340?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8113726953657435340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8113726953657435340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8113726953657435340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8113726953657435340'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/gotchas-for-cross-domain-portlets-via.html' title='Gotchas for Cross-domain Portlets via iFrames'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3271154900613635007</id><published>2010-04-02T12:34:00.012-04:00</published><updated>2010-12-22T13:31:53.677-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shib shibboleth shibbolize uportal login auth authn authorization'/><title type='text'>How to Shibbolize uPortal 2.5.3.2</title><content type='html'>We completed Shibbolization of our old version of uPortal (v2.5.3.2) today. Other than a good amount of work that various team members (Chris spent most of the time on it on the SP side) and I made to setup the SP and IdP's, the uPortal changes ended up not being so bad.
&lt;p/&gt;
Modify WEB-INF/classes/org/jasig/portal/channels/CLogin/html.xsl:
&lt;pre&gt;&lt;code&gt;
&amp;lt;!-- ~ If user is not authenticated insert login form--&amp;gt;
    &amp;lt;!-- ~ --&amp;gt;
    &amp;lt;xsl:template match=&amp;quot;login-status&amp;quot;&amp;gt;
        &amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;Login&amp;quot;&amp;gt;
            &amp;lt;fieldset id=&amp;quot;portalLogin&amp;quot;&amp;gt;
                &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;input class=&amp;quot;uportal-button&amp;quot; name=&amp;quot;Login&amp;quot; value=&amp;quot;Login&amp;quot; type=&amp;quot;submit&amp;quot; /&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;
                &amp;lt;xsl:apply-templates/&amp;gt;
            &amp;lt;/fieldset&amp;gt;
        &amp;lt;/form&amp;gt;  
    &amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
This assumes that you have configured Shibboleth to guard Login under uPortal (example: https://employees.acme.com/uPortal/Login).
&lt;p/&gt;
Modify WEB-INF/classes/properties/portal.properties:
&lt;pre&gt;&lt;code&gt;
org.jasig.portal.security.PersonManagerFactory.implementation=org.jasig.portal.security.provider.RemoteUserPersonManager
&lt;/code&gt;&lt;/pre&gt;

Modify WEB-INF/classes/properties/security.properties:
&lt;pre&gt;&lt;code&gt;
root=org.jasig.portal.security.provider.RemoteUserSecurityContextFactory
logoutRedirect.root=/Shibboleth.sso/Logout
&lt;/code&gt;&lt;/pre&gt;
and modify the logoutRedirect.root if needed.
&lt;p/&gt;
You can also disable/modify your logout link in (tomcat)/webapps/uPortal/WEB-INF/classes/org/jasig/portal/channels/CHeader/html.xsl and html_*.xsl in that dir.
&lt;p/&gt;
Other resources:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://shibboleth.internet2.edu/"&gt;Shibboleth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig"&gt;Apache config for Shib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Portal+Design"&gt;Design and Implementation of Shibbolizing uPortal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Home"&gt;ShibuPortal Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stufftohelpyouout.blogspot.com/2009/10/uportal-vs-liferay-comparison.html"&gt;Comment from Andrew Petro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spaces.internet2.edu/display/ShibuPortal/Shibbing+uPortal+JA-SIG+Session"&gt;Jasig unconference notes on shibbing uPortal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3271154900613635007?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3271154900613635007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3271154900613635007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3271154900613635007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3271154900613635007'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/04/shibbolizing-uportal-2532.html' title='How to Shibbolize uPortal 2.5.3.2'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6212414342153084300</id><published>2010-03-30T13:21:00.024-04:00</published><updated>2010-04-01T10:01:32.506-04:00</updated><title type='text'>Tags and Nested/Hierarchical/Categorical Organization</title><content type='html'>Today we were looking at data for an app we have internally that was organizing tagged data in a hierarchy of categories (nested categories). I assume that in the original design, categories were thought to be something helpful to guide the user into a sensible set of tags which which to filter the data.
&lt;p/&gt;
However, since the primary method of getting to the data was via categories, we are now seeing issues even with the small set of data that were caused because of the context of data being in a category, even if that data's tags did not adequately represent that context.
&lt;p/&gt;
For example, there was a category called "Vegetarian Selection" and under that category were three categories: "Excellent", "Good", and "Limited". The corresponding tags should have been called excellent_vegetarian_selection, good_vegetarian_selection, and limited_vegetarian_selection. However, the "Vegetarian Selection" category was the only way to access data tagged with those tags, so that context made the tags: excellent, good, and limited seem reasonable to whoever set them up. Even though it is a minor change required in data (the tag names), this method of giving context to tags from what category they are in would seem problematic.
&lt;p/&gt;
So how can you mix categories and tags and reduce the change of categorization giving the tag context? You could introduce the concept of "tag groups" and a sequential filtering by a member of these groups, similar to how Amazon does product browsing. For example:
&lt;p/&gt;
&lt;pre&gt;&lt;code&gt;
tag_group: building&lt;br/&gt;
tags: green_center, west_building, ...&lt;br/&gt;
tag_group: cuisine&lt;br/&gt;
tags: cafe, tex-mex, vegetarian, ...&lt;br/&gt;
tag_group: vegetarian_selection&lt;br/&gt;
tags: limited_vegetarian_selection, good_vegetarian_selection, ...&lt;br/&gt;
and maybe an automatically available tag_group (?) called: misc that would contain everything else not in a group&lt;br/&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
So instead of a single call to get a single nested categories list, there would be two calls to:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;return a list of tag_groups that have at least one tag that contained places associated with those tags, given the list of tags you are currently filtering by (which may be empty)&lt;/li&gt;
&lt;li&gt;return a list of tags that have places associated with those tags, given the list of tags you are currently filtering by (which may be empty)&lt;/li&gt;
&lt;/ul&gt;
&lt;p/&gt;
Using that solution, you could write something that keeps providing a list a tag_groups that you haven't defined a choice from yet. You keep choosing or you click on "all" to see a full list of places with the current list.
&lt;p/&gt;
However, it is worth noting that categorization and hierarchy/nesting introduces a risk of associating the context of the category with tags, so be careful if you mix the two.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6212414342153084300?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6212414342153084300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6212414342153084300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6212414342153084300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6212414342153084300'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/flat-organization-vs-hierarchy.html' title='Tags and Nested/Hierarchical/Categorical Organization'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2069671107127983549</id><published>2010-03-25T12:04:00.007-04:00</published><updated>2010-05-24T12:17:20.919-04:00</updated><title type='text'>Capistrano Deploy Issue in 2.5.10</title><content type='html'>When using set :keep_releases = (number) and Capistrano 2.5.10, it deleted the release it created on the server at the end of deployment. This would royally screw the deploy up, because in the end, the "current" symlink on the server would point to a non-existing release directory. I am very thankful that issue has been fixed between that version and current version, Capistrano 2.5.18.
&lt;p/&gt;
Since there were no errors in the log and you don't really pay attention to the release numbers in the log since they are so long, this really wasn't obvious at first. I couldn't find the bug for it when &lt;a href="https://capistrano.lighthouseapp.com/dashboard"&gt;searching&lt;/a&gt;, but perhaps you can. &lt;em&gt;Update: Lee helped me find the bug (&lt;a href="https://capistrano.lighthouseapp.com/projects/8716/tickets/88"&gt;#88&lt;/a&gt;) as discussed in bug &lt;a href="https://capistrano.lighthouseapp.com/projects/8716/tickets/155-deploy-issue-leaves-current-symlink-pointed-at-non-existent-directory"&gt;#155&lt;/a&gt;.&lt;/em&gt;
&lt;p/&gt;
I figured this out when I was doing text-replacement to remove the release numbers from the old log and new to help with the diff. Doing that I noticed that in the end of the log of the deploy using Capistano 2.5.10 removed the release it had deployed (!) in the end of the log.
&lt;pre&gt;&lt;code&gt;
  * executing "rm -rf /path/to/project/releases/(number of release just deployed)"
    servers: ["the.server.name"]
    [the.server.name] executing command
    command finished
&lt;/code&gt;&lt;/pre&gt;
I'm fairly sure that this had to do with the set :keep_releases, 3 that we were using for this particular project.
&lt;p/&gt;
So, the moral of the story is, if you are using Capistrano 2.5.10, be wary of :keep releases screwing up your deploy and leaving you with a current symlink pointed at a non-existant release dir. To fix, update capistrano via:
&lt;pre&gt;&lt;code&gt;
gem update capistrano
&lt;/code&gt;&lt;/pre&gt;
and redo your deployment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2069671107127983549?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2069671107127983549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2069671107127983549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2069671107127983549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2069671107127983549'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/capistrano-deploy-issue-in-2510.html' title='Capistrano Deploy Issue in 2.5.10'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1954378194555317039</id><published>2010-03-19T14:19:00.002-04:00</published><updated>2010-03-19T14:25:44.067-04:00</updated><title type='text'>LHC Operations</title><content type='html'>Follow the LHC on Twitter via &lt;a href="http://twitter.com/CMSexperiment"&gt;@CMSexperiment&lt;/a&gt; or via the &lt;a href="http://op-webtools.web.cern.ch/op-webtools/vistar/vistars.php?usr=LHC3"&gt;LHC Operations status&lt;/a&gt; online. Links courtesy of &lt;a href="http://science.slashdot.org/story/10/03/19/1530211/LHC-Hits-an-Energy-of-35TeV"&gt;this post on Slashdot&lt;/a&gt;. Took a screenshot of the LHC Operations status showing today's status:&lt;br/&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_dkSPoUrJq0E/S6PBl5Y4-YI/AAAAAAAAAn4/J_gDAaWWoA0/s1600-h/lhc+ops+status+2010-03-19.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 318px;" src="http://1.bp.blogspot.com/_dkSPoUrJq0E/S6PBl5Y4-YI/AAAAAAAAAn4/J_gDAaWWoA0/s400/lhc+ops+status+2010-03-19.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5450412830852970882" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1954378194555317039?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1954378194555317039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1954378194555317039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1954378194555317039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1954378194555317039'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/lhc-operations.html' title='LHC Operations'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_dkSPoUrJq0E/S6PBl5Y4-YI/AAAAAAAAAn4/J_gDAaWWoA0/s72-c/lhc+ops+status+2010-03-19.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7248847086563997615</id><published>2010-03-18T14:19:00.004-04:00</published><updated>2010-03-18T15:14:44.856-04:00</updated><title type='text'>Increase Side-by-side Diff Width for Terminal.app</title><content type='html'>For some reason, I always lived with --side-by-side diff getting chopped-off. I've found a new friend with specifying -W number or --width=number:
&lt;pre&gt;&lt;code&gt;
diff -b -y -W 280 file1 file2
&lt;/code&gt;&lt;/pre&gt;
Or the more lengthy version:
&lt;pre&gt;&lt;code&gt;
diff --side-by-side --width=280 --ignore-space-change file1 file2
&lt;/code&gt;&lt;/pre&gt;
Yes, there are nice graphical ones, but this works for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7248847086563997615?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7248847086563997615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7248847086563997615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7248847086563997615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7248847086563997615'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/no-frills-diffing-in-terminal.html' title='Increase Side-by-side Diff Width for Terminal.app'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1714970593454700209</id><published>2010-03-18T13:14:00.010-04:00</published><updated>2010-03-18T14:00:29.237-04:00</updated><title type='text'>Using sed to Escape Quotes</title><content type='html'>Using sed to escape quotes in a piped in value:
&lt;pre&gt;&lt;code&gt;
$ echo "\"hello\"" | sed s/\"/\\\\\\\"/g
\"hello\"
&lt;/code&gt;&lt;/pre&gt;
But backticks make it more interesting. Setting result of that into variable, via backticks:
&lt;pre&gt;&lt;code&gt;
$ resp=`echo "\"hello\"" | sed s/\"/\\\\\\\\\"/g`; echo $resp
\"hello\"
&lt;/code&gt;&lt;/pre&gt;
Just for kicks, backticks within backticks (see &lt;a href="http://stufftohelpyouout.blogspot.com/2010/03/multiple-backticks-require-lot-of.html"&gt;Escaping Backticks Within Backticks&lt;/a&gt;):
&lt;pre&gt;&lt;code&gt;
$ resp2=`resp1=\`echo "\"hello\"" | sed s/\"/\\\\\\\\\\\\\\\\\"/g\`; echo $resp1`;echo $resp2
\"hello\"
&lt;/code&gt;&lt;/pre&gt;
One more level of backticks:
&lt;pre&gt;&lt;code&gt;
$ resp3=`resp2=\`resp1=\\\`echo "\"hello\"" | sed s/\"/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"/g\\\`; echo $resp1\`;echo $resp2`;echo $resp3
\"hello\"
&lt;/pre&gt;&lt;/code&gt;
And another:
&lt;pre&gt;&lt;code&gt;
$ resp4=`resp3=\`resp2=\\\`resp1=\\\\\\\`echo "\"hello\"" | sed s/\"/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"/g\\\\\\\`; echo $resp1\\\`;echo $resp2\`;echo $resp3`;echo $resp4
\"hello\"
&lt;/code&gt;&lt;/pre&gt;
(Note: it can seem forgiving at times on the number of backticks if you have a few too many.)
&lt;p/&gt;
So, the number of backslashes required for the escaped slash replacement value is 7 if not within backticks. However, for each level of backticks, it requires &lt;a href="http://www.wolframalpha.com/input/?i=9%2C17%2C33%2C65%2C..."&gt;9,17,33,65&lt;/a&gt;,etc. backslashes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1714970593454700209?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1714970593454700209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1714970593454700209' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1714970593454700209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1714970593454700209'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/using-sed-to-escape-quotes.html' title='Using sed to Escape Quotes'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-9153219855814646077</id><published>2010-03-17T11:33:00.003-04:00</published><updated>2010-03-17T13:30:37.472-04:00</updated><title type='text'>Git Branching with Remote Tracking Made Easy</title><content type='html'>I wanted to be able to just create or switch to a new or existing remote/local git branch with a single command, so that you don't have to worry about whether you or a teammate already created a remote branch for a specific development request. It just works. While it can be used for any branch name, if you are using Jira, Trac, or a similar ticketing system, it might be good to use gbranch (ticket name). Then because the branches it creates are remotely tracked, you can git push and git pull without specifying the origin.
&lt;p/&gt;
To use it, create a file called gbranch.sh and chmod +x gbranch.sh and execute it in your start script (like .bash_profile, or whatever shell you use).
&lt;p/&gt;
This script is also included in my &lt;a href="http://github.com/garysweaver/git-scripts"&gt;git-scripts&lt;/a&gt; project.

&lt;pre&gt;&lt;code&gt;

# gbranch.sh
#
# Written by Gary S. Weaver
#
# Release: 2010-03-17
# This tracks a remote branch if it already exists, or
# makes a remotely tracking git branch if one doesn't exist, or
# just switches to the local branch by that name.

function gbranch () {
  branch=$1
  if test $# -eq 1
  then
    rbrch=`git branch -r`
    if [ &amp;quot;$?&amp;quot; -eq &amp;quot;0&amp;quot; ]
    then
      if [[ &amp;quot;$rbrch&amp;quot; =~ &amp;quot;origin/$branch&amp;quot; ]]
      then
        git checkout -b &amp;quot;$branch&amp;quot; --track &amp;quot;origin/$branch&amp;quot;
        if [ &amp;quot;$?&amp;quot; -ne &amp;quot;0&amp;quot; ]
        then
          git checkout &amp;quot;$branch&amp;quot;
        fi
      else
        git checkout -b &amp;quot;$branch&amp;quot;
        if [ &amp;quot;$?&amp;quot; -eq &amp;quot;0&amp;quot; ]
        then
          # The following lines track the remote branch per: http://djwonk.com/blog/2009/04/18/tracking-remote-git-branches/
          # note: first two lines help avoid  &amp;quot;fatal: Cannot force update the current branch.&amp;quot; error per DJWonk.
          git push origin &amp;quot;$branch&amp;quot;
          git checkout master
          git branch -f &amp;quot;$branch&amp;quot; &amp;quot;origin/$branch&amp;quot;
          git checkout &amp;quot;$branch&amp;quot;
        else
          git checkout &amp;quot;$branch&amp;quot;
        fi
      fi
    fi
  else
    echo usage: gbranch \(branch_name\)
  fi
}
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-9153219855814646077?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/9153219855814646077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=9153219855814646077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/9153219855814646077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/9153219855814646077'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/git-branching-with-remote-tracking-made.html' title='Git Branching with Remote Tracking Made Easy'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-8622968100483177503</id><published>2010-03-12T17:02:00.007-05:00</published><updated>2010-03-19T09:24:12.086-04:00</updated><title type='text'>Escaping Backticks within Backticks</title><content type='html'>If you have trouble with multiple backticks at command-line, it is because you aren't escaping them enough. It takes a lot more to escape then you might think at first. For example, in my last post I provided this example:
&lt;pre&gt;&lt;code&gt;
find `dirname \`dirname \\\`readlink -f \\\\\\\`which hg\\\\\\\`\\\`\`` -name mercurial
&lt;/code&gt;&lt;/pre&gt;
Here is another example:
&lt;pre&gt;&lt;code&gt;
dirname `dirname \`dirname \\\`dirname \\\\\\\`readlink -f \\\\\\\\\\\\\\\`which hg\\\\\\\\\\\\\\\`\\\\\\\`\\\`\``
&lt;/code&gt;&lt;/pre&gt;
So the pattern is that to escape you use &lt;a href="http://www.wolframalpha.com/input/?i=1%2C+3%2C+7%2C+15%2C+31%2C+..."&gt;1, 3, 7, 15, 31&lt;/a&gt;, etc. where the next number of backticks required is the previous number doubled, plus 1. This can get out-of-hand quickly, so try not to escape backticks within backticks too much if you don't have to.
&lt;p/&gt;
In addition, the level of backticks affects the number of backslashes required for escaping backslashes (example: &lt;a href="http://stufftohelpyouout.blogspot.com/2010/03/using-sed-to-escape-quotes.html"&gt;Using sed to Escape Quotes&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-8622968100483177503?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/8622968100483177503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=8622968100483177503' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8622968100483177503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/8622968100483177503'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/multiple-backticks-require-lot-of.html' title='Escaping Backticks within Backticks'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3589457562881721328</id><published>2010-03-12T16:55:00.016-05:00</published><updated>2010-03-17T10:23:41.122-04:00</updated><title type='text'>Converting a Mercurial Repo to Git</title><content type='html'>Using OS X 10.6.2 with Mercurial installed (via &lt;a href="http://www.macports.org/"&gt;Macports&lt;/a&gt;) and trying to use hg-fast-export.sh that &lt;a href="http://hopper.squarespace.com/blog/2008/7/5/converting-mercurial-to-git.html"&gt;Ben Hood posted about&lt;/a&gt; and Paul D. referred me to, I got the error:
&lt;pre&gt;&lt;code&gt;
ImportError: No module named mercurial
&lt;/code&gt;&lt;/pre&gt;
and according to &lt;a href="http://dynamicproxy.livejournal.com/38471.html"&gt;dynamicproxy&lt;/a&gt; this meant my PYTHONPATH env variable needed to be setup to include site-packages and site-packages/mercurial dirs.
&lt;p/&gt;
However, I had trouble at first finding those. In /usr/lib/python2.6/ there was no site-packages. In /Library/Python/2.6/site-packages/ there was no mercurial directory. I had also read that site-packages could be under ~/.local/, but I didn't have a ~/.local/. I figured out that I did in fact have a site-packages dir with mercurial dir in it by doing this:
&lt;pre&gt;&lt;code&gt;
$ which hg
/opt/local/bin/hg
&lt;/code&gt;&lt;/pre&gt;
I found the symlinked dir via:
&lt;pre&gt;&lt;code&gt;
$ ls -la /opt/local/bin/hg
lrwxr-xr-x  1 root  wheel  66 Nov 30 11:27 /opt/local/bin/hg -&gt; /opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin/hg
&lt;/code&gt;&lt;/pre&gt;
Then I looked under that dir to find mercurial:
&lt;pre&gt;&lt;code&gt;
$ find /opt/local/Library/Frameworks/Python.framework/Versions/2.6 -name mercurial
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/mercurial
&lt;/code&gt;&lt;/pre&gt;
Of course, with the power of multiple backticks, you could shorten that to:
&lt;pre&gt;&lt;code&gt;
$ find `dirname \`dirname \\\`readlink -f \\\\\\\`which hg\\\\\\\`\\\`\`` -name mercurial
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/mercurial
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
I added the following to ~/bash_profile.sh (notice the two paths in PYTHONPATH that were set to the path above and its parent dir) and killed/restarted Terminal.app:
&lt;pre&gt;&lt;code&gt;
export LC_CTYPE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export PYTHONPATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages:/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/mercurial:$PYTHONPATH
&lt;/code&gt;&lt;/pre&gt;
(note: before blinding copying and pasting that, you need to be sure that is the path to those dirs. See above.)
&lt;p/&gt;
If you want the repository to be hosted remotely, you may want to create an empty remote git repository that you will push the migrated hg repo to. This step is optional if you are just going to keep the git repo locally.
&lt;pre&gt;&lt;code&gt;
$ ssh username@someserver
$ sudo su - someotherusername
$ mkdir -p /path/to/remote/repo
$ chmod 775 /path/to/remote/repo
$ cd /path/to/remote/repo
$ git --bare init (with whatever options you want, for example: --shared=group)
&lt;/code&gt;&lt;/pre&gt;
Then, Ctrl-D twice to get back to your local environment.
&lt;p/&gt;
Back on my mac, I was able to successfully use hg-fast-export.sh per Ben Hood &lt;a href="http://hopper.squarespace.com/blog/2008/7/5/converting-mercurial-to-git.html"&gt;here&lt;/a&gt;: 
&lt;pre&gt;&lt;code&gt;
$ git clone git://repo.or.cz/fast-export.git
$ mkdir TARGET_REPO
$ cd TARGET_REPO
$ git init-db
$ ../fast-export/hg-fast-export.sh -r PATH_TO_LOCAL_HG_REPO
$ git remote add origin (remote repo path like username@someserver:/path/to/dir )
$ git push origin master
&lt;/code&gt;&lt;/pre&gt;
Then just to have a clean clone, go to a directory that should contain your git project directory and do this to get the converted git repo:
&lt;pre&gt;&lt;code&gt;
$ git clone ssh://username@someserver/path/to/remote/repo
&lt;/code&gt;&lt;/pre&gt;
Finally, you will probably want to create at least an additional branch in addition to production for development or testing and then track that branch.
&lt;p/&gt;
First, per &lt;a href="http://djwonk.com/blog/2009/04/18/tracking-remote-git-branches/"&gt;DJWonk's post&lt;/a&gt;, you may either want to enable automatic branch tracking globally via:
&lt;pre&gt;&lt;code&gt;
$ git config --global branch.autosetupmerge true
&lt;/code&gt;&lt;/pre&gt;
or do it for this repository:
&lt;pre&gt;&lt;code&gt;
$ git config branch.autosetupmerge true
&lt;/code&gt;&lt;/pre&gt;
Then, do the following to create a local branch (first line), make it remote (second line), and track it (rest of lines) (per &lt;a href="http://markelikalderon.com/blog/2008/08/26/pushing-and-tracking-remote-branches-with-git/%3Cbr%20%3E%3C/a%3E"&gt;Eli Kalderon's post&lt;/a&gt; that was recommended in &lt;a href="http://djwonk.com/blog/2009/04/18/tracking-remote-git-branches/"&gt;DJWonk's post&lt;/a&gt; about tracking git branches):
&lt;pre&gt;&lt;code&gt;
$ git checkout -b development
$ git push origin development
$ git checkout master
$ git branch -f development origin/development
$ git checkout development
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3589457562881721328?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3589457562881721328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3589457562881721328' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3589457562881721328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3589457562881721328'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/converting-mercurial-repo-to-git.html' title='Converting a Mercurial Repo to Git'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2830622362766024929</id><published>2010-03-11T15:29:00.018-05:00</published><updated>2010-03-12T10:27:00.652-05:00</updated><title type='text'>Thunderbird, Mail.app, and Exchange 2007 Rules, Filters, and Calendar Integration</title><content type='html'>I've been using &lt;a href="http://www.mozillamessaging.com/en-US/thunderbird/"&gt;Thunderbird&lt;/a&gt; in OS X for a few years now. For the most part it has worked pretty well. However, we were just asked to transition accounts from our current mail server to an exchange server. As part of this, we were told that Mail.app and iCal integrate well in Snow Leopard with the version of Exchange that is being used. The first thing I thought was, "How could I migrate/recreate my Thunderbird message filters/rules?" and the second was, "Can't I just use Thunderbird with Lightning for Exchange calendar integration?".
&lt;p/&gt;
I found that Thunderbird v2 stores its rules in a few places under your &lt;a href="http://www.mozilla.org/support/thunderbird/profile"&gt;Thunderbird profile&lt;/a&gt; in OS X: "/Users/username/Library/Thunderbird/Profiles/yourprofileid.default/ImapMail/imap.acme.com/msgFilterRules.dat" and "/Users/username/Library/Thunderbird/Profiles/yourprofileid.default/Mail/Local Folders/msgFilterRules.dat" in a format like:
&lt;pre&gt;&lt;code&gt;
version="8"
logging="no"
name="Acme Reports"
enabled="yes"
type="1"
action="Move to folder"
actionValue="imap://someusername@imap.acme.org/NameOfMoveToFolder"
condition="OR (to or cc,contains,acme-reports) OR (from,contains,someemail@acme.com) OR (subject,contains,Acme Report)"
... (repeat everything starting with name= over and over for each rule)
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
How about converting Thunderbird's filters to Mail.app format? Mail.app 4.2 stores its rules in "/Users/username/Library/Mail/MessageRules.plist" in a format like (just using the single rule above as example):
&lt;pre&gt;&lt;code&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
        &amp;lt;key&amp;gt;rules&amp;lt;/key&amp;gt;
        &amp;lt;array&amp;gt;
                &amp;lt;dict&amp;gt;
                        &amp;lt;key&amp;gt;Active&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AllCriteriaMustBeSatisfied&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AutoResponseType&amp;lt;/key&amp;gt;
                        &amp;lt;integer&amp;gt;0&amp;lt;/integer&amp;gt;
                        &amp;lt;key&amp;gt;CopyToMailbox&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;~/Library/Mail/IMAP-someusername@imap.acme.org/INBOX/NameOfMoveToFolder.imapmbox&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;CopyToMailboxURL&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;imap://someusername@imap.acme.org/INBOX/NameOfMoveToFolder&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;Criteria&amp;lt;/key&amp;gt;
                        &amp;lt;array&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;a5f2ada7-c0bd-4dff-a1bb-469545f1e5d4&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Expression&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;acme-reports&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;AnyRecipient&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;53c7189b-6772-42f8-a0ae-53d238d2d5b0&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Expression&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;someemail@acme.com&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;From&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;7952f5ae-22a6-445c-9657-35607d924d8e&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Expression&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;Acme Report&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;Subject&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                        &amp;lt;/array&amp;gt;
                        &amp;lt;key&amp;gt;Deletes&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;HighlightTextUsingColor&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;Mailbox&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;~/Library/Mail/IMAP-someusername@imap.acme.org/INBOX/NameOfMoveToFolder.imapmbox&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MailboxURL&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;imap://someusername@imap.acme.org/INBOX/NameOfMoveToFolder&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkFlagged&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkRead&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;NotifyUser&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleId&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;95880085-2370-4026-80F9-AEEA7BE9D4B2&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleName&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;Acme Reports&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldCopyMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldTransferMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;TimeStamp&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;195425409&amp;lt;/string&amp;gt;
                &amp;lt;/dict&amp;gt;
                &amp;lt;dict&amp;gt;
                        &amp;lt;key&amp;gt;Active&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AllCriteriaMustBeSatisfied&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AutoResponseType&amp;lt;/key&amp;gt;
                        &amp;lt;integer&amp;gt;0&amp;lt;/integer&amp;gt;
                        &amp;lt;key&amp;gt;Color&amp;lt;/key&amp;gt;
                        &amp;lt;integer&amp;gt;12096856&amp;lt;/integer&amp;gt;
                        &amp;lt;key&amp;gt;Criteria&amp;lt;/key&amp;gt;
                        &amp;lt;array&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;BD45A79F-79EB-4C22-AC0F-98D5B0768C8B&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;SenderIsNotInAddressBook&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;623B6201-0B02-4842-BA2A-4196435AD888&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;SenderIsNotInAddressHistory&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;83B3EE72-F2CB-4EF2-B060-EFA62209D11B&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;NoRecipientIncludesFullName&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;B95AD422-A4C2-4831-B8C6-A7837A23A578&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;IsJunkMail&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                        &amp;lt;/array&amp;gt;
                        &amp;lt;key&amp;gt;Deletes&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;HighlightTextUsingColor&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;IsOneAndOnlyJunkRule&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkFlagged&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkRead&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;NotifyUser&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleId&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;21A4628B-AF2A-4447-A38E-FA1FC2C7FA47&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleName&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;Junk&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldCopyMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldTransferMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;TimeStamp&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;195425409&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;Version&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;
                &amp;lt;/dict&amp;gt;
                &amp;lt;dict&amp;gt;
                        &amp;lt;key&amp;gt;Active&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AddInvitationAttachmentToICal&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AllCriteriaMustBeSatisfied&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;AutoResponseType&amp;lt;/key&amp;gt;
                        &amp;lt;integer&amp;gt;0&amp;lt;/integer&amp;gt;
                        &amp;lt;key&amp;gt;Criteria&amp;lt;/key&amp;gt;
                        &amp;lt;array&amp;gt;
                                &amp;lt;dict&amp;gt;
                                        &amp;lt;key&amp;gt;CriterionUniqueId&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;423D56D1-6FA3-4581-9E90-94632EE569D9&amp;lt;/string&amp;gt;
                                        &amp;lt;key&amp;gt;Header&amp;lt;/key&amp;gt;
                                        &amp;lt;string&amp;gt;AnyMessage&amp;lt;/string&amp;gt;
                                &amp;lt;/dict&amp;gt;
                        &amp;lt;/array&amp;gt;
                        &amp;lt;key&amp;gt;Deletes&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;HighlightTextUsingColor&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;IsOneAndOnlyICalRule&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;YES&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkFlagged&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;MarkRead&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;NotifyUser&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleId&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;28BF8471-E57D-4685-A059-3855AE1682FD&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;RuleName&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;Add Invitations Automatically&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldCopyMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;ShouldTransferMessage&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;NO&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;TimeStamp&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;195425409&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;Version&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;2&amp;lt;/string&amp;gt;
                &amp;lt;/dict&amp;gt;
        &amp;lt;/array&amp;gt;
        &amp;lt;key&amp;gt;version&amp;lt;/key&amp;gt;
        &amp;lt;integer&amp;gt;12&amp;lt;/integer&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
So if you wanted to convert Thunderbird message filters to Mail.app rule format, it might take some work to also set the timestamp, UUIDs, etc. inside each rule.
&lt;p/&gt;
I looked into the &lt;a href="https://addons.mozilla.org/en-US/thunderbird/addon/2474"&gt;Thunderbird Message Filter Import/Export 1.3.7.5&lt;/a&gt; Thunderbird plugin, but it basically exports in the same format as noted above except with two additional lines at the top for its import use:
&lt;pre&gt;&lt;code&gt;
RootFolderUri=imap://someusername@imap.acme.org
mailnews.customHeaders=
&lt;/code&gt;&lt;/pre&gt;
In addition, when Thunderbird starts, that plugin pops up the homepage of the add-on in a browser. I uninstalled it. It seemed just as easy to look at the files I mentioned if you are interested in the rules data, but let's hope that support for exporting filters to Mail.app rules format will be in a future version.
&lt;p/&gt;
As an alternative to using Mail.app to manage the rules, I was told that Exchange 2007's (rich/IE/"regular") OWA client could be used to setup server-side rules. (Note: Exchange Server 2007's Outlook Web Access Light client must be used if you don't use IE, and you can't manage server-side rules with non-IE browsers in that version of Exchange.) Running Windows XP in VMWare Fusion, and using &lt;a href="http://www.blunck.se/iehttpheaders/iehttpheaders.html"&gt;ieHTTPHeaders&lt;/a&gt; to view HTTP Headers in IE, it seemed that the process of adding rules via OWA (non-light/IE version) with Exchange 2007 was a session-based, multi-step process that had several IDs in the XML requests sent to Exchange during the process. It didn't seem very trivial to automate creation of even a single rule via scraping. However, I found reference of an exchange web service &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=134763"&gt;here&lt;/a&gt;. It looks like the URL to it typically looks like: http://someexchangeserver.somedomain.org/EWS/Exchange.asmx (see MS Exchange 2007 Exchange Web Services Managed API 1.0 docs &lt;a href="http://msdn.microsoft.com/en-us/library/dd637749%28EXCHG.80%29.aspx"&gt;intro&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/dd635461%28EXCHG.80%29.aspx"&gt;API docs&lt;/a&gt;). It would be nice if there were a plugin in Thunderbird to manage server-side rules in Exchange 2007 server, but I don't see any "Rule" object in the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data%28EXCHG.80%29.aspx"&gt;list of data classes&lt;/a&gt;.
&lt;p/&gt;
In addition, while Mail.app was more powerful than Thunderbird 2.0.0.x as far as rules went (for example- you could have it bounce in the dock if gets a high priority mail, or speak a name if an incoming mail matched the rules, etc.), I could not see how to get OWA to allow me to create a rule like "if to or cc contains ____" (you have to specify the exact text, it seemed, rather than to do a "contains").
&lt;p/&gt;
If you want to migrate rules from Thunderbird 2.0.0.26 to Mail.app v4.2 or Exchange Server 2007, just adding rules by hand in Mail.app or IE OWA client might be easiest, but note that Exchange 2007 OWA's rules may not let you do everything exactly the way you could in Thunderbird. However, if you use server-side rules, then when you connect via the web-based client, rules can be applied. So each have their benefits.
&lt;p/&gt;
Note that I'm having to switch from one mail server to another for incoming mail, though, so for me, a simple conversion of filters to rules wouldn't work. And because I don't want to have to start VMWare whenever I want to add rules, the OWA Exchange 2007 client is probably not a good option (once they switch to Exchange 2010 though, I might think about using Safari to manage rules, since that is claimed to be supported). I could just manually add folders and rules in Mail.app and that is probably what I'll do.
&lt;p/&gt;
I am not excluding sticking with Thunderbird either. Maybe Thunderbird's current (or future) integration with Exchange is (or will be) good enough. I installed Thunderbird 3 and &lt;a href="http://www.mozilla.org/projects/calendar/lightning/"&gt;Lightning&lt;/a&gt;. I'd also like to find Jamon Terrell's add-on as mentioned &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=134763"&gt;here&lt;/a&gt;. But I haven't found out yet how to hook Lightning/Thunderbird up to Exchange 2007 so that I could see my calendar, others' calendars, and respond to meeting requests easily.
&lt;p/&gt;
&lt;em&gt;(Specific versions of things I was working with: OS X 10.6.2, Thunderbird v2.0.0.24, Mail(.app) v4.2, and Exchange Server 2007.)&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2830622362766024929?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2830622362766024929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2830622362766024929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2830622362766024929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2830622362766024929'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/thunderbird-mailapp-exchange-owa-rules.html' title='Thunderbird, Mail.app, and Exchange 2007 Rules, Filters, and Calendar Integration'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6934744086493358256</id><published>2010-03-02T10:02:00.004-05:00</published><updated>2010-03-02T10:36:05.683-05:00</updated><title type='text'>ActiveScaffold and Column Order</title><content type='html'>At its simplest column order can be defined in the current version of ActiveScaffold as of 2010-03-02 with just:
&lt;pre&gt;&lt;code&gt;
active_scaffold :some_model do |config|
  config.columns = [:my_first_column_name, :my_second_column_name, :my_third_column_name, :my_fourth_column_name]
  ...
end
&lt;/code&gt;&lt;/pre&gt;
You can also set column weights to specify order like:
&lt;pre&gt;&lt;code&gt;
config.columns[my_first_column_name].weight = 20
&lt;/code&gt;&lt;/pre&gt;
But, if after definition (perhaps in a before_filter), you would like to exclude or add columns, like:
&lt;pre&gt;&lt;code&gt;
active_scaffold_config.list.columns.exclude :my_first_column_name
&lt;/code&gt;&lt;/pre&gt;
and then later do:
&lt;pre&gt;&lt;code&gt;
active_scaffold_config.list.columns.add :my_first_column_name
&lt;/code&gt;&lt;/pre&gt;
Then if you have "config.cache_classes = false" in your config/environments/development.rb, test.rb, and/or production.rb, you will need to have defined column weights for it to display :my_first_column_name as the first column rather than the last.
&lt;p/&gt;
However, if "config.cache_classes = true" config/environments/development.rb, test.rb, and/or production.rb, and you exclude and add that column back, it will disregard the weight and lose the column order (it will display :my_first_column_name as the last column rather than the first).
&lt;p/&gt;
A workaround for this provided by Sergio Cambra in &lt;a href="http://code.google.com/p/activescaffold/issues/detail?id=732"&gt;issue 732&lt;/a&gt; that worked for us is to specify:
&lt;pre&gt;&lt;code&gt;
active_scaffold_config.list.columns = active_scaffold_config.columns._inheritable
&lt;/code&gt;&lt;/pre&gt;
If you do this, you only need to define config.columns once like:
&lt;pre&gt;&lt;code&gt;
active_scaffold :some_model do |config|
  config.columns = [:my_first_column_name, :my_second_column_name, :my_third_column_name, :my_fourth_column_name]
  ...
end
&lt;/code&gt;&lt;/pre&gt;
and you don't have to define weights. Basically it is resetting the columns to the original set defined. This also means that you don't need to add columns back or exclude columns you added that you want to remove. This worked for us with config.cache_classes set to true or false in development.rb/test.rb/production.rb.
&lt;p/&gt;
However, if you need ActiveScaffold to keep track of multiple column excludes and adds historically through the session and you are using "config.cache_classes = true", you'd need to modify this workaround. If that is the case, and it is an option to use "config.cache_classes = false", you may just want to define weights and then add and exclude as much as you want.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6934744086493358256?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6934744086493358256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6934744086493358256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6934744086493358256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6934744086493358256'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/activescaffold-and-column-order.html' title='ActiveScaffold and Column Order'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4718795020146311826</id><published>2010-03-01T11:47:00.006-05:00</published><updated>2010-07-14T09:53:18.744-04:00</updated><title type='text'>HotCocoa/MacRuby Links</title><content type='html'>Here are some links to help you get started with HotCocoa development as of 2010/03/01:

&lt;h4&gt;MacRuby Intro&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.macruby.org/documentation/overview.html"&gt;http://www.macruby.org/documentation/overview.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;HotCocoa Tutorials&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stufftohelpyouout.blogspot.com/2010/02/create-macruby-hotcocoa-app.html"&gt;http://stufftohelpyouout.blogspot.com/2010/02/create-macruby-hotcocoa-app.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.macruby.org/hotcocoa/getting_started.html"&gt;http://www.macruby.org/hotcocoa/getting_started.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://isaac.kearse.co.nz/2010/02/01/packaging-hotcocoa/"&gt;http://isaac.kearse.co.nz/2010/02/01/packaging-hotcocoa/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;HotCocoa Examples&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/richkilmer/hotcocoa/tree/master/examples/"&gt;http://github.com/richkilmer/hotcocoa/tree/master/examples/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://isaac.kearse.co.nz/2010/01/31/stopwatch/"&gt;http://isaac.kearse.co.nz/2010/01/31/stopwatch/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Pretty pictures made by HotCocoa (must see)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://hcg.drtoast.com/category/examples/"&gt;http://hcg.drtoast.com/category/examples/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;More HotCocoa Graphics&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/mattetti/macruby_graphics"&gt;http://github.com/mattetti/macruby_graphics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;MacRuby Examples&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/masterkain/macruby/tree/master/sample/"&gt;http://github.com/masterkain/macruby/tree/master/sample/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;MacRuby/HotCocoa Source&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://github.com/masterkain/macruby/tree/master/sample-macruby/"&gt;http://github.com/masterkain/macruby/tree/master/sample-macruby/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/richkilmer/hotcocoa/"&gt;http://github.com/richkilmer/hotcocoa/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Support&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;HotCocoa issues: &lt;a href="http://github.com/richkilmer/hotcocoa/issues"&gt;http://github.com/richkilmer/hotcocoa/issues&lt;/a&gt;
&lt;li&gt;The only MacRuby list I think that people use: &lt;a href="http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel"&gt;http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rich is the HotCocoa guy: &lt;a href="http://richkilmer.blogs.com/"&gt;http://richkilmer.blogs.com/&lt;/a&gt;
&lt;li&gt;Laurent is the MacRuby guy at Apple: &lt;a href="http://chopine.be/"&gt;http://chopine.be/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p/&gt;
&lt;em&gt;Update 2010/06/10&lt;/em&gt;
&lt;p/&gt;
Dan Sinclair (see &lt;a href="http://github.com/dj2/hotcocoa
"&gt;his fork of HotCocoa&lt;/a&gt;) provided some links and an update via &lt;a href="http://lists.macosforge.org/pipermail/macruby-devel/2010-June/005263.html"&gt;an email on the MacRuby-devel mailing list&lt;/a&gt;. Here is what he said:
&lt;p/&gt;
&lt;blockquote&gt;
I've got a few tutorials and github apps that I've written with HotCocoa. I kinda stopped poking at it as I wasn't sure what the future held and decided to switch to straight up MacRuby/Cocoa for my last app.
&lt;p/&gt;
Tutorials&lt;br/&gt;
* &lt;a href="http://everburning.com/news/heating-up-with-hotcocoa-part-i/"&gt;http://everburning.com/news/heating-up-with-hotcocoa-part-i/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/heating-up-with-hotcocoa-part-ii/"&gt;http://everburning.com/news/heating-up-with-hotcocoa-part-ii/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/heating-up-with-hotcocoa-part-iii/"&gt;http://everburning.com/news/heating-up-with-hotcocoa-part-iii/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/heating-up-with-hotcocoa-on-github/"&gt;http://everburning.com/news/heating-up-with-hotcocoa-on-github/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/download-and-xml-parsing-with-hotcocoa/"&gt;http://everburning.com/news/download-and-xml-parsing-with-hotcocoa/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/toolbars-with-hotcocoa/"&gt;http://everburning.com/news/toolbars-with-hotcocoa/&lt;/a&gt;&lt;br/&gt;
* &lt;a href="http://everburning.com/news/hotcocoa-and-core-data/"&gt;http://everburning.com/news/hotcocoa-and-core-data/&lt;/a&gt;&lt;br/&gt;
&lt;p/&gt;
Github&lt;br/&gt;
* &lt;a href="http://github.com/dj2/SilverLining"&gt;http://github.com/dj2/SilverLining&lt;/a&gt;   (Amazon EC2 Instance Browser)&lt;br/&gt;
* &lt;a href="http://github.com/dj2/Rife"&gt;http://github.com/dj2/Rife&lt;/a&gt;                 (Start of a news reader)&lt;br/&gt;
* &lt;a href="http://github.com/dj2/Postie"&gt;http://github.com/dj2/Postie&lt;/a&gt;             (The app from the heating up tutorials)&lt;br/&gt;
&lt;p/&gt;
&lt;p/&gt;
dan
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4718795020146311826?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4718795020146311826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4718795020146311826' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4718795020146311826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4718795020146311826'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/03/hotcocoamacruby-links.html' title='HotCocoa/MacRuby Links'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2767506729932629391</id><published>2010-02-26T12:53:00.002-05:00</published><updated>2010-02-26T12:56:12.471-05:00</updated><title type='text'>Log to Console in Rails Console</title><content type='html'>When you are in the Rails console (./script/console), you might want to see what is being logged through the Rails logger in standard out. To do that, just use:
&lt;pre&gt;&lt;code&gt;
ActiveRecord::Base.logger = Logger.new(STDOUT)
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2767506729932629391?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2767506729932629391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2767506729932629391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2767506729932629391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2767506729932629391'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/log-to-console-in-rails-console.html' title='Log to Console in Rails Console'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-7705252458941569534</id><published>2010-02-26T10:49:00.007-05:00</published><updated>2010-02-26T13:07:20.620-05:00</updated><title type='text'>Seconds to Days, Minutes, Hours, Seconds in Ruby</title><content type='html'>Here is how to convert a large number of seconds into days, months, hours, seconds format using Ruby (using similar in the &lt;a href="http://github.com/garysweaver/hourz"&gt;Hourz&lt;/a&gt; application). total_seconds is the difference between two Ruby &lt;a href="http://ruby-doc.org/core/classes/Time.html"&gt;Time&lt;/a&gt; instances:
&lt;pre&gt;&lt;code&gt;
  def display_time(total_seconds)
    total_seconds = total_seconds.to_i
    
    days = total_seconds / 86400
    hours = (total_seconds / 3600) - (days * 24)
    minutes = (total_seconds / 60) - (hours * 60) - (days * 1440)
    seconds = total_seconds % 60
    
    display = ''
    display_concat = ''
    if days &amp;gt; 0
      display = display + display_concat + &amp;quot;#{days}d&amp;quot;
      display_concat = ' '
    end
    if hours &amp;gt; 0 || display.length &amp;gt; 0
      display = display + display_concat + &amp;quot;#{hours}h&amp;quot;
      display_concat = ' '
    end
    if minutes &amp;gt; 0 || display.length &amp;gt; 0
      display = display + display_concat + &amp;quot;#{minutes}m&amp;quot;
      display_concat = ' '
    end
    display = display + display_concat + &amp;quot;#{seconds}s&amp;quot;
    display
  end
&lt;/code&gt;&lt;/pre&gt;
Example in irb:
&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; display_time(Time.at(12345678) - Time.at(1234567))
=&amp;gt; &amp;quot;128d 14h 25m 11s&amp;quot;
&amp;gt;&amp;gt; display_time(Time.at(123456789) - Time.at(12345678))
=&amp;gt; &amp;quot;1286d 0h 11m 51s&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
Here is a modification that doesn't show minutes if there are days left and doesn't show seconds if there are days or hours left:
&lt;pre&gt;&lt;code&gt;
  def display_brief_time(total_seconds)
    total_seconds = total_seconds.to_i
    
    days = total_seconds / 86400
    hours = (total_seconds / 3600) - (days * 24)
    minutes = (total_seconds / 60) - (hours * 60) - (days * 1440)
    seconds = total_seconds % 60
    
    display = ''
    display_concat = ''
    if days &amp;gt; 0
      display = display + display_concat + &amp;quot;#{days}d&amp;quot;
      display_concat = ' '
    end
    if hours &amp;gt; 0 || days &amp;gt; 0
      display = display + display_concat + &amp;quot;#{hours}h&amp;quot;
      display_concat = ' '
    end
    if days == 0 &amp;amp;&amp;amp; (minutes &amp;gt; 0 || hours &amp;gt; 0)
      display = display + display_concat + &amp;quot;#{minutes}m&amp;quot;
      display_concat = ' '
    end
    if hours == 0 &amp;amp;&amp;amp; days == 0
      display = display + display_concat + &amp;quot;#{seconds}s&amp;quot;
    end
    display
  end
&lt;/code&gt;&lt;/pre&gt;
Example of that in irb:
&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt; display_brief_time(Time.at(12345678) - Time.at(1234567))
=&amp;gt; &amp;quot;128d 14h&amp;quot;
&amp;gt;&amp;gt; display_brief_time(Time.at(12345678) - Time.at(12345677))
=&amp;gt; &amp;quot;1s&amp;quot;
&amp;gt;&amp;gt; display_brief_time(Time.at(12345678) - Time.at(12345607))
=&amp;gt; &amp;quot;1m 11s&amp;quot;
&amp;gt;&amp;gt; display_brief_time(Time.at(12345678) - Time.at(12340607))
=&amp;gt; &amp;quot;1h 24m&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
To make it even more brief, you could not show seconds unless there are less than 3 minutes left with:
&lt;pre&gt;&lt;code&gt;
def display_very_brief_time(total_seconds)
    total_seconds = total_seconds.to_i
    
    days = total_seconds / 86400
    hours = (total_seconds / 3600) - (days * 24)
    minutes = (total_seconds / 60) - (hours * 60) - (days * 1440)
    seconds = total_seconds % 60
    
    display = ''
    display_concat = ''
    if days &amp;gt; 0
      display = display + display_concat + &amp;quot;#{days}d&amp;quot;
      display_concat = ' '
    end
    if hours &amp;gt; 0 || days &amp;gt; 0
      display = display + display_concat + &amp;quot;#{hours}h&amp;quot;
      display_concat = ' '
    end
    if days == 0 &amp;amp;&amp;amp; (minutes &amp;gt; 0 || hours &amp;gt; 0)
      display = display + display_concat + &amp;quot;#{minutes}m&amp;quot;
      display_concat = ' '
    end
    if hours == 0 &amp;amp;&amp;amp; days == 0 &amp;amp;&amp;amp; minutes &amp;lt; 3
      display = display + display_concat + &amp;quot;#{seconds}s&amp;quot;
    end
    display
  end
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-7705252458941569534?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/7705252458941569534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=7705252458941569534' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7705252458941569534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/7705252458941569534'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/seconds-to-days-minutes-hours-seconds.html' title='Seconds to Days, Minutes, Hours, Seconds in Ruby'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4193682299324362958</id><published>2010-02-25T10:16:00.006-05:00</published><updated>2010-02-25T11:13:56.749-05:00</updated><title type='text'>How to Fix Audio Issues After OS X 10.6 Upgrade from OS X 10.5</title><content type='html'>&lt;em&gt;Note: Some mention in &lt;a href="http://forums.mactalk.com.au/11/72243-snow-leopard-sound-bug.html"&gt;this post&lt;/a&gt; that this didn't work for them, or the directory wasn't even there, but the fix that Matt Notley noted worked for me! Thanks to Matt and to whoever figured this out, if it wasn't Matt originally!&lt;/em&gt;
&lt;p/&gt;
After being unable to hearing streaming audio via Adobe Acrobat Connect after the upgrade from OS X 10.5 to 10.6 (Snow Leopard) (and subsequent patches to OS X 10.6.2), even after going into System Preferences -&amp;gt; Sound and adjusting volume and setting the device (I use a Eutectics IPP200), I was unable to hear any sound. If I set my sound output to speaker I could hear it fine, but I just wasn't able to play sound for that particular application through that USB device.
&lt;p/&gt;
&lt;h3&gt;Fix&lt;/h3&gt;
I did a Google search for "snow leopard sound issue" and the top post was "Snow Leopard Sound Bug? - MacTalk Forums". In &lt;a href="http://forums.mactalk.com.au/11/72243-snow-leopard-sound-bug.html"&gt;that post&lt;/a&gt;, Matt Notley (mattnotley2004) of Melbourne, VIC states, 'In " Macintosh HD / Library / Preferences / Audio " there are two audio setting files. Delete them. Set your sound to the desired setting. Restart. You may have trouble logging on after a restart, if this happens... just power off your Mac for 10 seconds, then turn it back on. Your sound issue should now be fixed!!'
&lt;p/&gt;
I backed up the files just in case by just moving them to Desktop like:
&lt;pre&gt;&lt;code&gt;
sudo mv /Library/Preferences/Audio/* ~/Desktop/
&lt;/code&gt;&lt;/pre&gt;
and then closed all applications and restarted. After I rebooted, I opened System Preferences -&amp;gt; Sound and noticed that it retained the setting to use my USB device for sound output.
&lt;p/&gt;
I also checked to make sure that the /Library/Preferences/Audio/com.apple.audio.DeviceSettings.plist and /Library/Preferences/Audio/com.apple.audio.SystemSettings.plist had been created. I then went back to that same presentation I had previously been unable to hear, and was able to listen to it via my USB device!
&lt;p/&gt;
&lt;h3&gt;What Did This Change?&lt;/h3&gt;
For those wishing to see what the difference was in the files- I can't say for certain that the ownership of the files changed, but the new owner is _coreaudiod. Here are the diffs, showing that the "input streams" key and settings section was missing from com.apple.audio.DeviceSettings.plist. This is a diff of old (broken) vs. new (working) files:
&lt;pre&gt;&lt;code&gt;
$ diff /Users/.../Desktop/com.apple.audio.DeviceSettings.plist /Library/Preferences/Audio/com.apple.audio.DeviceSettings.plist
434c434
&amp;lt;     &amp;lt;real&amp;gt;1&amp;lt;/real&amp;gt;
---
&amp;gt;     &amp;lt;real&amp;gt;0.77777779102325439&amp;lt;/real&amp;gt;
444c444
&amp;lt;     &amp;lt;real&amp;gt;1&amp;lt;/real&amp;gt;
---
&amp;gt;     &amp;lt;real&amp;gt;0.77777779102325439&amp;lt;/real&amp;gt;
700a701,1066
&amp;gt;   &amp;lt;key&amp;gt;input streams&amp;lt;/key&amp;gt;
&amp;gt;   &amp;lt;array&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;   &amp;lt;/array&amp;gt;
&amp;gt;   &amp;lt;key&amp;gt;output streams&amp;lt;/key&amp;gt;
&amp;gt;   &amp;lt;array&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;    &amp;lt;dict&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bits per channel&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;32&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;bytes per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;4&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;channels per frame&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format flags&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;25&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;format id&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1819304813&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;frames per packet&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;integer&amp;gt;1&amp;lt;/integer&amp;gt;
&amp;gt;     &amp;lt;key&amp;gt;sample rate&amp;lt;/key&amp;gt;
&amp;gt;     &amp;lt;real&amp;gt;44100&amp;lt;/real&amp;gt;
&amp;gt;    &amp;lt;/dict&amp;gt;
&amp;gt;   &amp;lt;/array&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
Here is the diff of com.apple.audio.SystemSettings.plist (old broken vs. new fixed). It made some changes and removed several keys:
&lt;pre&gt;&lt;code&gt;
$ diff /Users/.../Desktop/com.apple.audio.SystemSettings.plist /Library/Preferences/Audio/com.apple.audio.SystemSettings.plist
8c8
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineInput:1B,0,1,0:3&amp;lt;/string&amp;gt;
---
&amp;gt;   &amp;lt;string&amp;gt;AppleUSBAudioEngine:Eutectics Inc.:Eutectics IPP200:07162001-01:2&amp;lt;/string&amp;gt;
10,12c10
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineOutput:1B,0,1,2:0&amp;lt;/string&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;current default system output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineOutput:1B,0,1,2:0&amp;lt;/string&amp;gt;
---
&amp;gt;   &amp;lt;string&amp;gt;AppleUSBAudioEngine:Eutectics Inc.:Eutectics IPP200:07162001-01:1&amp;lt;/string&amp;gt;
22,36d19
&amp;lt;   &amp;lt;key&amp;gt;primary default input device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleUSBAudioEngine:Eutectics Inc.:Eutectics IPP200:07162001-01:2&amp;lt;/string&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;primary default output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleUSBAudioEngine:Eutectics Inc.:Eutectics IPP200:07162001-01:1&amp;lt;/string&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;primary default system output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleUSBAudioEngine:Eutectics Inc.:Eutectics IPP200:07162001-01:1&amp;lt;/string&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;secondary default output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineOutput:1B,0,1,2:0&amp;lt;/string&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;secondary default system output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineOutput:1B,0,1,2:0&amp;lt;/string&amp;gt;
&amp;lt;  &amp;lt;/dict&amp;gt;
&amp;lt;  &amp;lt;key&amp;gt;92&amp;lt;/key&amp;gt;
&amp;lt;  &amp;lt;dict&amp;gt;
&amp;lt;   &amp;lt;key&amp;gt;current default system output device&amp;lt;/key&amp;gt;
&amp;lt;   &amp;lt;string&amp;gt;AppleHDAEngineOutput:1B,0,1,2:0&amp;lt;/string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4193682299324362958?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4193682299324362958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4193682299324362958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4193682299324362958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4193682299324362958'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/how-to-fix-audio-issues-after-os-x-106.html' title='How to Fix Audio Issues After OS X 10.6 Upgrade from OS X 10.5'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-9215243749248333830</id><published>2010-02-23T15:55:00.016-05:00</published><updated>2010-02-23T16:45:54.866-05:00</updated><title type='text'>hg serve and hg glog</title><content type='html'>If you want to view Mercurial changes graphically, there are at least two choices: hg serve (web-based version) and hg glog (command-line version).
&lt;p/&gt;
For the first, you do:
&lt;pre&gt;&lt;code&gt;
hg serve
&lt;/code&gt;&lt;/pre&gt;
then go to &lt;a href="http://localhost:8000/"&gt;http://localhost:8000/&lt;/a&gt;, then click "graph" on the top left, and by repeated clicking "more" on the top right, you will find the changes you want to see.
&lt;p/&gt;
We pushed the graph of changes to the limit today and we couldn't fully see the stuff we were interested on the far right, because it was cut-off:
&lt;p/&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_dkSPoUrJq0E/S4RC88aDPBI/AAAAAAAAAcc/EFjjfCI9-48/s1600-h/hg_serve_graph.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 111px; height: 400px;" src="http://1.bp.blogspot.com/_dkSPoUrJq0E/S4RC88aDPBI/AAAAAAAAAcc/EFjjfCI9-48/s400/hg_serve_graph.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5441547864545377298" /&gt;&lt;/a&gt;
&lt;p/&gt;
Richard told me about the &lt;a href="http://mercurial.selenic.com/wiki/GraphlogExtension"&gt;Graph log extension&lt;/a&gt; for Mercurial to see branches at command-line (in Terminal.app), which was able to do a better job at displaying the change history graphically than hg serve did.
&lt;p/&gt;
To use that, edit ~/.hgrc and add "hgext.graphlog = " under [extensions]. Then:
&lt;pre&gt;&lt;code&gt;
hg glog
&lt;/code&gt;&lt;/pre&gt;
which produces output like the following that doesn't break. I attempted to use the same changesets as shown above in the pic for an apples-to-apples comparison, even though it looks a bit different:
&lt;pre&gt;&lt;code&gt;
| o---------+ | |  changeset:   ...
|   | | | | | | |  user:        ...
|  / / / / / / /   date:        ...
| | | | | | | |    summary:     ...
| | | | | | | |
| | | | | o | |    changeset:   ...
| | | | | |\ \ \   parent:      ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
| | +-------o | |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
o---------+ | | |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
| | | | | o | | |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
o-----------+ | |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
| | | | | | o | |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
o-------------+ |  changeset:   ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  parent:      ...
| | | | | | | | |  user:        ...
| | | | | | | | |  date:        ...
| | | | | | | | |  summary:     ...
| | | | | | | | |
| | | | | | | o |  changeset:   ...
| | | | | | | |/   parent:      ...
| | | | | | | |    user:        ...
| | | | | | | |    date:        ...
| | | | | | | |    summary:     ...
| | | | | | | |
o-------------+  changeset:   ...
| | | | | | | |  parent:      ...
| | | | | | | |  parent:      ...
| | | | | | | |  user:        ...
| | | | | | | |  date:        ...
| | | | | | | |  summary:     ...
| | | | | | | |
| | +---------o  changeset:   ...
| | | | | | |    parent:      ...
| | | | | | |    user:        ...
| | | | | | |    date:        ...
| | | | | | |    summary:     ...
| | | | | | |
o-----------+  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
| | | | | | o  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
o | | | | | |  changeset:   ...
|\| | | | | |  parent:      ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
| o | | | | |  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
o | | | | | |  changeset:   ...
|\| | | | | |  parent:      ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
| o | | | | |  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
o | | | | | |  changeset:   ...
|\| | | | | |  parent:      ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
| o | | | | |  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
| | | | | | |
o-----------+  changeset:   ...
| | | | | | |  parent:      ...
| | | | | | |  parent:      ...
| | | | | | |  user:        ...
| | | | | | |  date:        ...
| | | | | | |  summary:     ...
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-9215243749248333830?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/9215243749248333830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=9215243749248333830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/9215243749248333830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/9215243749248333830'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/mercurial-serve-graph-vs-ascii-graph.html' title='hg serve and hg glog'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_dkSPoUrJq0E/S4RC88aDPBI/AAAAAAAAAcc/EFjjfCI9-48/s72-c/hg_serve_graph.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1205648211711791143</id><published>2010-02-19T10:46:00.010-05:00</published><updated>2010-02-19T11:21:43.273-05:00</updated><title type='text'>Read a File to a String in Ruby</title><content type='html'>Reading a file into a String in Ruby is much easier than most examples I've found show that it is, probably because they are old. Reading a File into a String in Ruby is just:
&lt;pre&gt;&lt;code&gt;
  f = File.open('filename','r')
  s = f.read
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Looking at ActiveRecord, I noticed that the implementations of from_json used something similar to the following code in the beginning of each method:
&lt;pre&gt;&lt;code&gt;
  def output(some_input)
    if respond_to? :read
      some_input = some_input.read
    end
    p some_input
  end
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
So by including those three lines, you add the ability for any method to either take a String or a File as the parameter/argument, so your method can a File:
&lt;pre&gt;&lt;code&gt;
  f = File.open('filename','r')
  output(f)
&lt;/code&gt;&lt;/pre&gt;
just as easily as it can take a String:
&lt;pre&gt;&lt;code&gt;
  output('Hello, World!')
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1205648211711791143?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1205648211711791143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1205648211711791143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1205648211711791143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1205648211711791143'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/read-file-to-string-in-ruby.html' title='Read a File to a String in Ruby'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4948243981788168858</id><published>2010-02-17T16:27:00.002-05:00</published><updated>2010-02-17T16:41:14.683-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os_x macruby hotcocoa github'/><title type='text'>HotCocoa App to Track Time on Tasks</title><content type='html'>Just wrote a HotCocoa/MacRuby OS X app called &lt;a href="http://github.com/garysweaver/hourz"&gt;Hourz&lt;/a&gt; to track time on tasks. HotCocoa and MacRuby are both pretty awesome, and the Cocoa framework obviously is even more-so. I was able to &lt;a href="http://stufftohelpyouout.blogspot.com/2010/02/create-macruby-hotcocoa-app.html"&gt;get a quick application up and running quickly&lt;/a&gt; and of course &lt;a href="http://stufftohelpyouout.blogspot.com/2010/02/create-custom-icon-of-your-hotcocoa-app.html"&gt;make a neat little icon&lt;/a&gt; to show up in the dock.
&lt;p/&gt;
That said, I did run into some issues. However, it is what you expect when learning a new framework and a new language that are both relatively new also. However, I expect if there is continued effort in both MacRuby and HotCocoa development, it might become a great way to write OS X applications quickly even for someone not familiar with Cocoa.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4948243981788168858?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4948243981788168858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4948243981788168858' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4948243981788168858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4948243981788168858'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/hotcocoa-app-to-track-time-on-tasks.html' title='HotCocoa App to Track Time on Tasks'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2020850597129332316</id><published>2010-02-16T16:09:00.002-05:00</published><updated>2010-02-16T16:11:42.943-05:00</updated><title type='text'>MacRuby IRB Console</title><content type='html'>Just use the following at command-line to start up a MacRuby IRB session:
&lt;pre&gt;&lt;code&gt;
macirb
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2020850597129332316?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2020850597129332316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2020850597129332316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2020850597129332316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2020850597129332316'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/macruby-irb-console.html' title='MacRuby IRB Console'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4894125815069998948</id><published>2010-02-16T10:15:00.012-05:00</published><updated>2010-02-16T11:57:59.738-05:00</updated><title type='text'>Create a Custom Icon for Your HotCocoa App</title><content type='html'>If you've written an application for Mac OS X in HotCocoa, one of the first things you probably want to do is to change the icon. This is simple to do, but I didn't see it documented anywhere.
&lt;p/&gt;
The following process uses tools freely available for OS X (I use OS X 10.6.2) to create and change the icon.
&lt;p/&gt;
First, grab Seashore if you need an image editor. If you have a non-rectangular image and want to use a transparency, &lt;a href="http://seashore.sourceforge.net/forum/thread.php?thread=148"&gt;use the tip here&lt;/a&gt;. If you want it to look like the rest of the icons, see &lt;a href="http://developer.apple.com/mac/library/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIcons/XHIGIcons.html#//apple_ref/doc/uid/20000967-TP6"&gt;Icons&lt;/a&gt; in the Apple Human Interface Guidelines document on Apple's site. If you have photoshop you could try something like &lt;a href="http://www.keepthewebweird.com/iphone-style-icon-tutorial/"&gt;this&lt;/a&gt;. But, unless you need it to look professional, just save the image.
&lt;p/&gt;
Open &lt;a href="http://www.img2icnsapp.com/"&gt;Img2icns&lt;/a&gt; and drag the image into it. The free version works fine for this, but I recommend buying the pro version, even if only to fund their development. You can tell where the transparency will be in the icon by where you see the blueish background within the area. Then click on Icns in Img2icns to create the icns file.
&lt;p/&gt;
Copy that file to the resources directory in your HotCocoa project and name it (name of app).icns. If you are not sure what to name it, look in the built application (after calling macrake) that resides in (name of app).app/Contents/Resources/. By default the HotCocoa macrake build copies HotCocoa.icns to (app name).icns unless you provide a (name of app).icns in the (project name)/resources directory.
&lt;p&gt;
Call macrake and see the new icon for your app! If you already had your app in the dock, you might need to remove it from the dock to see the icon change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4894125815069998948?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4894125815069998948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4894125815069998948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4894125815069998948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4894125815069998948'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/create-custom-icon-of-your-hotcocoa-app.html' title='Create a Custom Icon for Your HotCocoa App'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-2011104297275146564</id><published>2010-02-15T09:56:00.005-05:00</published><updated>2010-02-15T10:10:46.393-05:00</updated><title type='text'>Call Some Toll-free Numbers Free Internationally Using Skype</title><content type='html'>Recently on the uportal-users list Conan Cook was asking how they could call a U.S. Toll-free phone number from the UK, and Cris Holdorph replied that he could use Skype. I just looked into it and Skype has a list of the countries that have toll-free numbers that you can call from anywhere using Skype (using SkypeOut, even though you don't have to pay for it). Just do a search in the page for "Toll Free" to see which countries' toll-free numbers you can call with Skype:&lt;br/&gt;
* &lt;a href="http://www.skype.com/prices/callrates/#allRatesTab"&gt;http://www.skype.com/prices/callrates/#allRatesTab&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-2011104297275146564?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/2011104297275146564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=2011104297275146564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2011104297275146564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/2011104297275146564'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/call-some-toll-free-numbers-free.html' title='Call Some Toll-free Numbers Free Internationally Using Skype'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1702811227800712667</id><published>2010-02-11T11:00:00.015-05:00</published><updated>2010-02-11T11:38:42.997-05:00</updated><title type='text'>Get Request Param Values in Javascript</title><content type='html'>The following should get any request parameter from the URL, escaping all characters used in regular expressions:
&lt;pre&gt;&lt;code&gt;
function getReqParam(name)
{
  var regexpstr = &amp;quot;[\\?&amp;amp;]&amp;quot;+escapeRegExp(name)+&amp;quot;=([^&amp;amp;#]*)&amp;quot;;
  var arr = new RegExp(regexpstr).exec(window.location.href);
  if(arr == null) return null;
  return arr[1];
}

function escapeRegExp(value) {
  return value.replace(/\\/g,&amp;quot;\\\\&amp;quot;).replace(/\//g,&amp;quot;\\\/&amp;quot;).replace(/\./g,&amp;quot;\\\.&amp;quot;).replace(/\*/g,&amp;quot;\\\*&amp;quot;).replace(/\+/g,&amp;quot;\\\+&amp;quot;).replace(/\?/g,&amp;quot;\\\?&amp;quot;).replace(/\|/g,&amp;quot;\\\|&amp;quot;).replace(/\(/g,&amp;quot;\\\(&amp;quot;).replace(/\)/g,&amp;quot;\\\)&amp;quot;).replace(/\[/g,&amp;quot;\\\[&amp;quot;).replace(/\]/g,&amp;quot;\\\]&amp;quot;).replace(/\{/g,&amp;quot;\\\{&amp;quot;).replace(/\}/g,&amp;quot;\\\}&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
Here is a example test HTML that you can use to see how it works by specifying the request parameter as the target (like ?someparam=somevalue#someparam), just for the heck of it.
&lt;pre&gt;&lt;code&gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;test&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;script language=&amp;quot;javascript&amp;quot; type=&amp;quot;text/javascript&amp;quot; defer&amp;gt;
&amp;lt;!--
function getReqParam(name)
{
  var regexpstr = &amp;quot;[\\?&amp;amp;]&amp;quot;+escapeRegExp(name)+&amp;quot;=([^&amp;amp;#]*)&amp;quot;;
  var arr = new RegExp(regexpstr).exec(window.location.href);
  if(arr == null) return null;
  return arr[1];
}

function escapeRegExp(value) {
  return value.replace(/\\/g,&amp;quot;\\\\&amp;quot;).replace(/\//g,&amp;quot;\\\/&amp;quot;).replace(/\./g,&amp;quot;\\\.&amp;quot;).replace(/\*/g,&amp;quot;\\\*&amp;quot;).replace(/\+/g,&amp;quot;\\\+&amp;quot;).replace(/\?/g,&amp;quot;\\\?&amp;quot;).replace(/\|/g,&amp;quot;\\\|&amp;quot;).replace(/\(/g,&amp;quot;\\\(&amp;quot;).replace(/\)/g,&amp;quot;\\\)&amp;quot;).replace(/\[/g,&amp;quot;\\\[&amp;quot;).replace(/\]/g,&amp;quot;\\\]&amp;quot;).replace(/\{/g,&amp;quot;\\\{&amp;quot;).replace(/\}/g,&amp;quot;\\\}&amp;quot;);
}

window.location.href=&amp;quot;?\/.*+?|(){}[]{}=asdf#\/.*+?|(){}[]{}&amp;quot;
if (window.location.hash == null || window.location.hash.length &amp;lt; 2) {
  document.write(&amp;quot;modify the url to specify req param and hash (target) is the req param name&amp;quot;)
} else {
  document.write( &amp;quot;request param name '&amp;quot; + window.location.hash + &amp;quot;'=&amp;quot; + getReqParam(window.location.hash.substr(1)) + &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;);
}
--&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
I didn't find any other examples that allowed all of the characters ""/.*+?|(){}[]{}"" in the request parameter name, even though the likelihood of that is low for most applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1702811227800712667?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1702811227800712667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1702811227800712667' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1702811227800712667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1702811227800712667'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/get-request-param-values-in-javascript.html' title='Get Request Param Values in Javascript'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-1872892915629305584</id><published>2010-02-05T10:25:00.008-05:00</published><updated>2010-02-08T12:07:27.248-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rails activesupport from_xml xml parse string duplicate keys'/><title type='text'>Hash.from_xml and Multiple Elements with Same Name</title><content type='html'>I've seen reference to ActiveSupport's Hash.from_xml method to easily parse XML into hashes, but I assumed that it would overwrite keys when the same element name was defined multiple times while in the same context, as you would think it might, but it doesn't (which is a good thing).
&lt;p/&gt;
Some examples:
&lt;pre&gt;&lt;code&gt;
Hash.from_xml &amp;quot;&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;&amp;lt;tags&amp;gt;&amp;lt;tag&amp;gt;apple&amp;lt;/tag&amp;gt;&amp;lt;tag&amp;gt;orange&amp;lt;/tag&amp;gt;&amp;lt;/tags&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
produces the hash:
&lt;pre&gt;&lt;code&gt;
{&amp;quot;a&amp;quot;=&amp;gt;{&amp;quot;b&amp;quot;=&amp;gt;{&amp;quot;tags&amp;quot;=&amp;gt;{&amp;quot;tag&amp;quot;=&amp;gt;[&amp;quot;apple&amp;quot;, &amp;quot;orange&amp;quot;]}}}}
&lt;/code&gt;&lt;/pre&gt;
and
&lt;pre&gt;&lt;code&gt;
Hash.from_xml &amp;quot;&amp;lt;a&amp;gt;&amp;lt;b&amp;gt;&amp;lt;a&amp;gt;1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;apple&amp;lt;/b&amp;gt;&amp;lt;a&amp;gt;2&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;banana&amp;lt;/b&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
produces the hash:
&lt;pre&gt;&lt;code&gt;
{&amp;quot;a&amp;quot;=&amp;gt;{&amp;quot;b&amp;quot;=&amp;gt;{&amp;quot;a&amp;quot;=&amp;gt;[&amp;quot;1&amp;quot;, &amp;quot;2&amp;quot;], &amp;quot;b&amp;quot;=&amp;gt;[&amp;quot;apple&amp;quot;, &amp;quot;banana&amp;quot;]}}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Please note that well-designed XML should usually not use unencapsulated key/value pairs in a XML like:
&lt;pre&gt;&lt;code&gt;
&amp;lt;keypairs&amp;gt;&amp;lt;key&amp;gt;key1&amp;lt;/key&amp;gt;&amp;lt;value&amp;gt;value1&amp;lt;/value&amp;gt;&amp;lt;key&amp;gt;key2&amp;lt;/key&amp;gt;&amp;lt;value&amp;gt;value2&amp;lt;/value&amp;gt;&amp;lt;/keypairs&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
but I've had to consume XML like this before (very recently).
&lt;p/&gt;
Note that XML attributes can be lost as noted in &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/1598-preserve-xml-attributes-with-hashfrom_xml-and-activeresource"&gt;ticket #1598&lt;/a&gt;, but perhaps that will be fixed in a future version of ActiveSupport/Rails.
&lt;p/&gt;
If you get "NoMethodError: undefined method `from_xml' for Hash:Class", remember that Rails includes ActiveSupport. If you're not using Rails, you need to:
&lt;pre&gt;&lt;code&gt;
require 'rubygems'                          
require 'active_support'
&lt;/code&gt;&lt;/pre&gt;
After playing with REXML and XmlSimple a little previously, this seems to be one of the easier ways to consume XML in Ruby/JRuby, if you want to work with most of the data in the supplied in the XML (and if you either don't need XML attributes or &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/1598-preserve-xml-attributes-with-hashfrom_xml-and-activeresource"&gt;ticket #1598&lt;/a&gt; gets fixed). However, it isn't always that great. Depending on the xml, it might produce hashes and arrays sometimes and not other times when multiples are not defined, ending with code that has respond_to? :each and respond_to? :keys , etc. So, it is not a solution for every case, but it sometimes provides a fairly simple solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-1872892915629305584?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/1872892915629305584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=1872892915629305584' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1872892915629305584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/1872892915629305584'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/hashfromxml-and-multiple-elements-with.html' title='Hash.from_xml and Multiple Elements with Same Name'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4123164066182546976</id><published>2010-02-02T13:50:00.013-05:00</published><updated>2010-03-31T16:05:52.046-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='macruby ruby os_x mac hotcocoa'/><title type='text'>Create a MacRuby HotCocoa App</title><content type='html'>You can create an OS X app quickly in Snow Leopard (OS 10.6.x) or later with &lt;a href="http://www.macruby.org/"&gt;MacRuby&lt;/a&gt; and &lt;a href="http://www.macruby.org/trac/wiki/HotCocoa"&gt;HotCocoa&lt;/a&gt;.
&lt;p/&gt;
Much of this information was provided in Isaac Kearse's post, &lt;a href="http://isaac.kearse.co.nz/2010/02/01/packaging-hotcocoa/"&gt;Packaging A HotCocoa Application&lt;/a&gt;, which I'd recommend reading also as it has more information than I've included, and a lot of this is copied as a backup from Isaac's post. It's Ruby, so a lot of it should be familiar.
&lt;p/&gt;
1. &lt;a href="http://www.macruby.org/"&gt;Download MacRuby&lt;/a&gt;.
&lt;p/&gt;
2. Double-click on the zip file to extract it and double-click on the package inside the extracted directory to start the install. Just go with the defaults.
&lt;p/&gt;
3. You may want to kill off terminal.app if you have it running and restart it, just in case the install put anything into the environment.
&lt;p/&gt;
4. Use the following to install the hotcocoa macgem:
&lt;pre&gt;&lt;code&gt;
sudo macgem install hotcocoa
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
5. Change to the directory that you want your project directory to reside in:
&lt;pre&gt;&lt;code&gt;
mkdir -p /path/to/my/projects/
cd /path/to/my/projects/
&lt;/code&gt;&lt;/pre&gt;
6. Create a sample hotcocoa app:
&lt;pre&gt;&lt;code&gt;
hotcocoa nameofyourapp
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Once you've done what you want, you can build and run your sample hotcocoa app via:
&lt;pre&gt;&lt;code&gt;
cd nameofyourapp
macrake
&lt;/code&gt;&lt;/pre&gt;
and deploy it via:
&lt;pre&gt;&lt;code&gt;
macrake deploy
&lt;/code&gt;&lt;/pre&gt;
If it won't work, run it so that you can see the error in terminal.app:
&lt;pre&gt;&lt;code&gt;
macruby lib/application.rb --debug
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
If you're curious, you can see what other macgems are available via:
&lt;pre&gt;&lt;code&gt;
sudo macgem list --remote
&lt;/code&gt;&lt;/pre&gt;
If you want to include a custom icon, see &lt;a href="http://stufftohelpyouout.blogspot.com/2010/02/create-custom-icon-of-your-hotcocoa-app.html"&gt;my other post&lt;/a&gt;.
&lt;p/&gt;
Again, thanks much to Isaac Kearse's post, &lt;a href="http://isaac.kearse.co.nz/2010/02/01/packaging-hotcocoa/"&gt;Packaging A HotCocoa Application&lt;/a&gt;, which contains even more information than I've provided here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4123164066182546976?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4123164066182546976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4123164066182546976' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4123164066182546976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4123164066182546976'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/02/create-macruby-hotcocoa-app.html' title='Create a MacRuby HotCocoa App'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3163168316254116675</id><published>2010-01-28T10:17:00.012-05:00</published><updated>2010-08-18T11:47:27.245-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git prompt'/><title type='text'>Show Name of Git Branch in Prompt</title><content type='html'>The following shows you how to have a nifty prompt in OS X like
&lt;pre&gt;&lt;code&gt;
[myhostname dirname (git branch name)]$
&lt;/code&gt;&lt;/pre&gt;
when you are in a git project, and
&lt;pre&gt;&lt;code&gt;
[myhostname dirname]$
&lt;/code&gt;&lt;/pre&gt;
when you aren't. Works for me in OS X 10.6.2 (Snow Leopard) and for another co-worker that tried it in OS X 10.5.x.
&lt;p/&gt;
Basically you just need to call the bash script that does git completion, and then set the prompt.
&lt;p/&gt;
&lt;em&gt;Updated Aug 18, 2010 with instructions for Homebrew.&lt;/em&gt;
&lt;p/&gt;
&lt;h3&gt;Using Homebrew&lt;/h3&gt;
This assumes you installed Git via &lt;a href="http://github.com/mxcl/homebrew"&gt;Homebrew&lt;/a&gt;. If you haven't installed Homebrew or Git yet, the instructions are on the Homebrew site, which I'd recommend, but here are the commands to do that, as of August 2010:
&lt;pre&gt;&lt;code&gt;
ruby -e &amp;quot;$(curl -fsS http://gist.github.com/raw/323731/install_homebrew.rb)&amp;quot;
brew install wget
brew install git
brew update
&lt;/code&gt;&lt;/pre&gt;
then add this to the bottom of your ~/.bash_profile, ~/.profile, or ~/.zshrc:
&lt;pre&gt;&lt;code&gt;
# see: http://stufftohelpyouout.blogspot.com/2010/01/show-name-of-git-branch-in-prompt.html
# see also: http://superuser.com/questions/31744/how-to-get-git-completion-bash-to-work-on-mac-os-x
# see also: http://stackoverflow.com/questions/347901/what-are-your-favorite-git-features-or-tricks
# This assumes you have installed Homebrew ( http://github.com/mxcl/homebrew )
# and then installed Git via Homebrew with the default installation location:
# ruby -e &amp;quot;$(curl -fsS http://gist.github.com/raw/323731/install_homebrew.rb)&amp;quot;
# brew install wget
# brew install git
# brew update
if [ -f /usr/local/etc/bash_completion.d/git-completion.bash ]; then
  . /usr/local/etc/bash_completion.d/git-completion.bash;
  PS1='[\h \W$(__git_ps1 &amp;quot; (%s)&amp;quot;)]\$ ';
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Using MacPorts&lt;/h3&gt;
&lt;p/&gt;
For this I had installed Git via the Google Code &lt;a href="http://code.google.com/p/git-osx-installer/"&gt;git-osx-installer&lt;/a&gt;.
&lt;p/&gt;
First install &lt;a href="http://macports.org/"&gt;MacPorts&lt;/a&gt;. Then do:
&lt;pre&gt;&lt;code&gt;
sudo port selfupdate
sudo port install git-core +bash_completion
&lt;/code&gt;&lt;/pre&gt;
then add this to the bottom of your ~/.bash_profile, ~/.profile, or ~/.zshrc:
&lt;pre&gt;&lt;code&gt;
# see: http://stufftohelpyouout.blogspot.com/2010/01/show-name-of-git-branch-in-prompt.html
# see also: http://superuser.com/questions/31744/how-to-get-git-completion-bash-to-work-on-mac-os-x
# see also: http://stackoverflow.com/questions/347901/what-are-your-favorite-git-features-or-tricks
# install http://macports.org/
# sudo port selfupdate
# sudo port install git-core +bash_completion
if [ -f /opt/local/etc/bash_completion ]; then
    . /opt/local/etc/bash_completion
    PS1='[\h \W$(__git_ps1 &amp;quot; (%s)&amp;quot;)]\$ '
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
Then completely close Terminal.app and reopen it. When you cd into a dir containing a git project, you will see the currently checked out git branch within parentheses at the end of the prompt.
&lt;p/&gt;
This solution is based on &lt;a href="http://stackoverflow.com/questions/347901/what-are-your-favorite-git-features-or-tricks"&gt;this prompt tip from Casey&lt;/a&gt; and the setup and related bit needed in .bash_profile is based on &lt;a href="http://superuser.com/questions/31744/how-to-get-git-completion-bash-to-work-on-mac-os-x"&gt;this tip on setting up git-completion from Adam Johnson&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3163168316254116675?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3163168316254116675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3163168316254116675' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3163168316254116675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3163168316254116675'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/01/show-name-of-git-branch-in-prompt.html' title='Show Name of Git Branch in Prompt'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-294414325638311937</id><published>2010-01-27T11:31:00.017-05:00</published><updated>2010-02-05T13:19:47.865-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git repository'/><title type='text'>2 Minute Guide to Remote Git Repository Creation</title><content type='html'>This is basically the same as the 37signals &lt;a href="https://37s.backpackit.com/pub/1465067"&gt;Git Resources&lt;/a&gt; Creating a remote repository section, with some minor modifications and clarifications. Both are geared toward someone who wants to create a repository accessible to only people in certain group.
&lt;p&gt;&lt;/p&gt;
First off, login to the remote server:
&lt;pre&gt;&lt;code&gt;
ssh userid@yourremoteserver
&lt;/code&gt;&lt;/pre&gt;
Let's assume that you already setup a user "otheruserid" (maybe you created a "git" user) that is in the same group as the developers that need access to the repository. We'll assume that "userid" is a member of that same group. It is a better idea to create this as a more generic user that won't be removed later, so that the group membership can be dynamic (as people come and go). Note that the .git at the end of the path is optional.
&lt;pre&gt;&lt;code&gt;
sudo su - otheruserid
mkdir -p /some/path/nameofmyproject.git
chmod 775 /some/path/nameofmyproject.git
cd /some/path/nameofmyproject.git
&lt;/code&gt;&lt;/pre&gt;
For this next part, don't change group to the group name. It is literally supposed to be this exact line if you want to share with the group. If you want it to be open to the public, you'd specify "all" instead of "group".
&lt;pre&gt;&lt;code&gt;
git --bare init --shared=group
(Ctrl-D twice to get back to your local environment)
&lt;/code&gt;&lt;/pre&gt;
Richard mentioned that if you want to create a private group repository and manage permissions across everything a little better you could use getacl/setacl (even
though you should still use --shared=group, just in case). You can probably find more on permissions via a search, but berliOS has a GIT HowTo with a section on &lt;a href="http://developer.berlios.de/docman/display_doc.php?docid=1812&amp;amp;group_id=2#access"&gt;How to control access to your GIT Repository&lt;/a&gt; just as one example of fine-grained permissions.
&lt;p&gt;
Back on your computer, or wherever you want to develop, do the following:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;
mkdir -p /path/to/my/projects/dir
cd /path/to/my/projects/dir
mkdir nameofmyproject
&lt;/code&gt;&lt;/pre&gt;
Be careful that you change directory into your new nameofmyproject directory, otherwise you could end up adding everything that is not nailed down (via git) into your new repository!
&lt;pre&gt;&lt;code&gt;
cd nameofmyproject
git init
git remote add origin userid@yourremoteserver:/some/path/nameofmyproject.git
touch .gitignore
git add .
git commit -m "Initial commit"
git push --all
&lt;/code&gt;&lt;/pre&gt;
Ok, now you have the local copy, but if you try to do "git pull" it won't work because the following isn't defined in .git/config:
&lt;pre&gt;&lt;code&gt;
[branch "master"]
 remote = origin
 merge = refs/heads/master
&lt;/code&gt;&lt;/pre&gt;
&lt;p/&gt;
You could edit .git/config to add that to the bottom, or better yet- blow away the local project directory you just created (please back it up first if it is important!) and clone from the remote repo:
&lt;pre&gt;&lt;code&gt;
cd ..
rm -rf nameofproject (warning: back it up first, if you are unsure about removing it)
git clone ssh://userid@yourremoteserver/some/path/nameofmyproject.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
If someone else wants to clone the repository to work with it locally, they do this:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;
git clone ssh://userid@yourremoteserver/some/path/nameofmyproject.git
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-294414325638311937?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/294414325638311937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=294414325638311937' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/294414325638311937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/294414325638311937'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/01/2-minute-guide-to-remote-git-repository.html' title='2 Minute Guide to Remote Git Repository Creation'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-4393632590062153841</id><published>2010-01-25T12:16:00.008-05:00</published><updated>2010-02-05T13:20:22.880-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby gem version ssh remote'/><title type='text'>Remotely Determining Ruby, RubyGems, and Gem Versions via ssh</title><content type='html'>The following one liner displays the ruby executable's version, RUBY_VERSION, the RubyGems version, and lists all gems:
&lt;pre&gt;&lt;code&gt;
ssh userid@server 'ruby -v &amp;&amp; echo RUBY_VERSION: &amp;&amp; ruby -e "p RUBY_VERSION" &amp;&amp; echo RubyGems version: &amp;&amp; gem -v &amp;&amp; echo Installed gems: &amp;&amp; gem list'
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-4393632590062153841?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/4393632590062153841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=4393632590062153841' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4393632590062153841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/4393632590062153841'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/01/remotely-determining-rubygems-and-gem.html' title='Remotely Determining Ruby, RubyGems, and Gem Versions via ssh'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3728185949491059161</id><published>2010-01-14T14:26:00.007-05:00</published><updated>2010-02-05T13:21:47.236-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cap capistrano capshell command-line multiple'/><title type='text'>Send Capshell Commands in Single Command-line</title><content type='html'>You can echo multiple lines and pipe them into capshell like:
&lt;pre&gt;&lt;code&gt;
echo "some command 1" "some command 2" | capshell
&lt;/code&gt;&lt;/pre&gt;
That starts capshell and runs some command 1 and then some command 2. Simple, but I thought it was neat, especially if you just want to create an alias to check for something via a short command line like:
&lt;pre&gt;&lt;code&gt;
alias e=cd /path/to/rails/project &amp;&amp; echo "with appservers" "grep -r some_text /path/on/server/to/app/current/log" | capshell
&lt;/code&gt;&lt;/pre&gt;
then at command line you just type 'e' and it will grep all app server logs for some_text.
&lt;p/&gt;
For more info about capshell, see &lt;a href="http://www.capify.org/index.php/Capistrano"&gt;Capistrano&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-3728185949491059161?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/3728185949491059161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=3728185949491059161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3728185949491059161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/3728185949491059161'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/01/send-capshell-commands-in-single.html' title='Send Capshell Commands in Single Command-line'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-6406282190855760824</id><published>2010-01-05T12:44:00.013-05:00</published><updated>2010-10-27T14:57:17.373-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby oci8 os_x mac snow_leopard'/><title type='text'>Fix for undefined method `define_a_column' for class `OCI8::Cursor' (NameError) in OS X 10.6 (Snow Leopard)</title><content type='html'>If you're using Ruby with ruby-oci8 in OS X 10.6 (Snow Leopard), you may get the following error:
&lt;pre&gt;&lt;code&gt;
$ ./script/server
=&amp;gt; Booting WEBrick...
./script/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb:536: undefined method `define_a_column' for class `OCI8::Cursor' (NameError)
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/activerecord/lib/active_record.rb:81
from ./script/../config/../vendor/rails/activerecord/lib/active_record.rb:80:in `each'
from ./script/../config/../vendor/rails/activerecord/lib/active_record.rb:80
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:162:in `require_frameworks'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:162:in `each'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:162:in `require_frameworks'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:83:in `process'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:43:in `send'
from ./script/../config/../vendor/rails/railties/lib/initializer.rb:43:in `run'
from ./script/../config/../config/environment.rb:11
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/railties/lib/commands/servers/webrick.rb:52
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/railties/lib/commands/server.rb:39
from ./script/server:3:in `require'
from ./script/server:3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
First off, read &lt;a href="http://blog.rayapps.com/2009/09/06/how-to-setup-ruby-and-oracle-instant-client-on-snow-leopard/"&gt;Raimonds Simanovskis's great post&lt;/a&gt; on how to setup Ruby and Oracle instant client on Snow Leopard, if you haven't already. Note that the environment variables are different for different operating systems (see &lt;a href="http://download.oracle.com/docs/cd/B19306_01/server.102/b15658/prcmp_cll_int.htm#CACDIFAD"&gt;Oracle documentation&lt;/a&gt;). You may get the same or similar error by not having an environment variable missing/misspelled/setup incorrectly.
&lt;/p&gt;&lt;p&gt;
If you get the error I mentioned above, you might have a problem with version 2.0.0 and higher of ruby-oci8 as &lt;a href="http://www.ruby-forum.com/topic/182145"&gt;noted by Brendan Boesen&lt;/a&gt;. Assuming you have everything else working, just uninstall ruby-oci8 and install the older version, compiling it for 64-bit Intel architecture via:
&lt;/p&gt;&lt;pre&gt;&lt;code&gt;
gem uninstall ruby-oci8
env DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH ARCHFLAGS="-arch x86_64" gem install ruby-oci8 --version "&amp;lt; 2.0.0"
&lt;/code&gt;&lt;/pre&gt;
After doing that, I tried ./script/server again, and it worked fine.
&lt;p/&gt;
&lt;em&gt;Update: October 27, 2010: With Rails 3 you can use Ruby-oci8 2.0.4, and Oracle Enhanced Adapter 1.3.1. See &lt;a href="http://blog.rayapps.com/2010/09/09/oracle-enhanced-adapter-1-3-1-and-how-to-use-it-with-rails3/"&gt;this post&lt;/a&gt;.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7557194597309413467-6406282190855760824?l=stufftohelpyouout.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stufftohelpyouout.blogspot.com/feeds/6406282190855760824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7557194597309413467&amp;postID=6406282190855760824' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6406282190855760824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7557194597309413467/posts/default/6406282190855760824'/><link rel='alternate' type='text/html' href='http://stufftohelpyouout.blogspot.com/2010/01/fix-for-undefined-method-defineacolumn.html' title='Fix for undefined method `define_a_column&apos; for class `OCI8::Cursor&apos; (NameError) in OS X 10.6 (Snow Leopard)'/><author><name>Gary S. Weaver</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='22' src='http://4.bp.blogspot.com/_dkSPoUrJq0E/SKHXqMLQPlI/AAAAAAAAABs/MH5hzTvA6W4/s1600-R/gary_s_weaver.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7557194597309413467.post-3255918479299933226</id><published>2010-01-04T12:19:00.021-05:00</published><updated>2010-02-05T13:23:30.137-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby ra
