<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkIARn4zeip7ImA9WxBREEg.&quot;"><id>tag:blogger.com,1999:blog-6958306</id><updated>2009-12-28T22:49:07.082-05:00</updated><title>Two Four One</title><subtitle type="html">Semi-Random thoughts on life, computers, sports, and what not.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://twofourone.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>289</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TwoFourOne" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;AkIARn4yeCp7ImA9WxBREEg.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-2202193237277486560</id><published>2009-12-28T22:47:00.001-05:00</published><updated>2009-12-28T22:49:07.090-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-28T22:49:07.090-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>TrExMa 0.8.6</title><content type="html">TrophyManager again changed their Squad page.  I've finally been able to find some time around the holidays to fix the TrExMa plugin.&lt;br /&gt;&lt;br /&gt;It's available at &lt;a href="http://code.google.com/p/trexma-for-firefox/"&gt;Google Code&lt;/a&gt; as version 0.8.6.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-2202193237277486560?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BT6D7rayoqMRjBsa29SVc_AXvJg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BT6D7rayoqMRjBsa29SVc_AXvJg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BT6D7rayoqMRjBsa29SVc_AXvJg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BT6D7rayoqMRjBsa29SVc_AXvJg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=AjcdmJRINkk:PyEU7_BDQ74:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=AjcdmJRINkk:PyEU7_BDQ74:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=AjcdmJRINkk:PyEU7_BDQ74:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=AjcdmJRINkk:PyEU7_BDQ74:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=AjcdmJRINkk:PyEU7_BDQ74:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=AjcdmJRINkk:PyEU7_BDQ74:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=AjcdmJRINkk:PyEU7_BDQ74:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=AjcdmJRINkk:PyEU7_BDQ74:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/AjcdmJRINkk" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="TrExMa 0.8.6" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/2202193237277486560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=2202193237277486560" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2202193237277486560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2202193237277486560?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/AjcdmJRINkk/trexma-086.html" title="TrExMa 0.8.6" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/12/trexma-086.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QEQHs6fCp7ImA9WxNbFEs.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-7738363552401046955</id><published>2009-11-17T08:56:00.008-05:00</published><updated>2009-11-17T09:48:21.514-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-17T09:48:21.514-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Woot-Off" /><category scheme="http://www.blogger.com/atom/ns#" term="winstone" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Simple Web Tool Building With Maven (The Woot-Off Tracker Revisited)</title><content type="html">&lt;p&gt;One of my favorite tools of the past year was the &lt;a href="http://twofourone.blogspot.com/2008/11/air-based-woot-off-tracker.html"&gt;Woot-Off&lt;/a&gt; &lt;a href="http://twofourone.blogspot.com/2008/12/spry-woot-off-tracker.html"&gt;tracker&lt;/a&gt; I developed just over a year ago.  In my mind, one of the problems this tool had was that I needed to start up a proxy server to host make calls on behalf of the AJAX Javascript.  I needed to find some way to make this easier.  Additionally, I had run into an issue when I actually tried to run the tool behind a firewall proxy.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Since discovering the power of Maven, I thought I'd look into seeing what was available for the Winstone servlet engine I used on the first iteration of this tool.  Conviently, there was the &lt;a href="http://alchim.sourceforge.net/winstone-maven-plugin/usage.html"&gt;winstone-maven-plugin&lt;/a&gt;, a mojo which, among other things, built an executable jar for winstone with your war already deployed.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This was perfect for my needs.  So (along with converting to apache's http-client) I set out on a new maven adventure.  My pom looked like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="XML"&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;com.twofourone&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;woot.tracker.proxy&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;&lt;br /&gt; &amp;lt;name&amp;gt;woot.tracker.proxy&amp;lt;/name&amp;gt;&lt;br /&gt; &amp;lt;url&amp;gt;http://twofourone.blogspot.coom&amp;lt;/url&amp;gt;&lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;servlet-api&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.4&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;javax.servlet.jsp&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;jsp-api&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.0&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;4.6&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.apache.httpcomponents&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;httpclient&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;4.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;/dependencies&amp;gt;&lt;br /&gt; &amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;     &amp;lt;source&amp;gt;1.5&amp;lt;/source&amp;gt;&lt;br /&gt;     &amp;lt;target&amp;gt;1.5&amp;lt;/target&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;net.sf.alchim&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;winstone-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;     &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;       &amp;lt;goal&amp;gt;embed&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;&lt;br /&gt;     &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;net.sf.alchim&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;winstone-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.2&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;     &amp;lt;cmdLineOptions&amp;gt;&lt;br /&gt;      &amp;lt;property&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;httpPort&amp;lt;/name&amp;gt;&lt;br /&gt;       &amp;lt;value&amp;gt;8480&amp;lt;/value&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;ajp13Port&amp;lt;/name&amp;gt;&lt;br /&gt;       &amp;lt;value&amp;gt;-1&amp;lt;/value&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;controlPort&amp;lt;/name&amp;gt;&lt;br /&gt;       &amp;lt;value&amp;gt;-1&amp;lt;/value&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;directoryListings&amp;lt;/name&amp;gt;&lt;br /&gt;       &amp;lt;value&amp;gt;false&amp;lt;/value&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;useInvoker&amp;lt;/name&amp;gt;&lt;br /&gt;       &amp;lt;value&amp;gt;false&amp;lt;/value&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;     &amp;lt;/cmdLineOptions&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;     &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;       &amp;lt;goal&amp;gt;embed&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;&lt;br /&gt;     &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;finalName&amp;gt;woot.tracker.proxy&amp;lt;/finalName&amp;gt;&lt;br /&gt; &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We have two setups for winstone.  The first goal, &lt;span style="font-style: italic;"&gt;embed&lt;/span&gt;, tells Maven to stick winstone into the jar during the package phase.  By default, this step will create a jar with the same name as your project and throw &lt;span style="font-style: italic;"&gt;-standalone&lt;/span&gt; on the end. The second setup tells winstone what port it should run on, etc.  These could potentially be in a single setup, just haven't tried it yet.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In order to run the proxy, you simply execute the jar from a command prompt and you'll have a war deployed to port 8480. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;How has our proxy changed?  In order to support a firewall call, I decided to use Apache's &lt;a href="http://hc.apache.org/httpcomponents-client/index.html"&gt;HttpClient&lt;/a&gt;. Adding the dependency for HttpClient to the pom automagically downloads all dependencies of HttpClient for use by the war.  Our new code looks like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="AS3"&gt;&lt;br /&gt;package com.twofourone.woot.tracker.proxy;&lt;br /&gt;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.io.OutputStream;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;import javax.servlet.http.HttpServlet;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;import javax.servlet.http.HttpServletResponse;&lt;br /&gt;&lt;br /&gt;import org.apache.http.HttpEntity;&lt;br /&gt;import org.apache.http.HttpHost;&lt;br /&gt;import org.apache.http.HttpResponse;&lt;br /&gt;import org.apache.http.client.HttpClient;&lt;br /&gt;import org.apache.http.client.methods.HttpGet;&lt;br /&gt;import org.apache.http.conn.params.ConnRoutePNames;&lt;br /&gt;import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Proxy Servlet to redirect requests to the Woot site.&lt;br /&gt;* @author mcornell&lt;br /&gt;*/&lt;br /&gt;public class WootProxy extends HttpServlet {&lt;br /&gt;&lt;br /&gt;   static final long serialVersionUID = 1L;&lt;br /&gt;&lt;br /&gt;   private HttpClient httpClient = new DefaultHttpClient();&lt;br /&gt;   private HttpGet wootGet;&lt;br /&gt;  &lt;br /&gt; /**&lt;br /&gt;  * Sets up the HttpClient with proxy info if provided. Sets up the URL for Woot.&lt;br /&gt;  */&lt;br /&gt; @Override&lt;br /&gt; public void init() throws ServletException {&lt;br /&gt;  String proxyHost = System.getProperty("proxyHost", "");&lt;br /&gt;    &lt;br /&gt;    String proxyPort = System.getProperty("proxyPort", "");&lt;br /&gt;    &lt;br /&gt;    if (proxyHost.length() &gt; 0 &amp;amp;&amp;amp; proxyPort.length() &gt; 0) {&lt;br /&gt;     HttpHost proxy = new HttpHost(proxyHost, Integer.parseInt(proxyPort));&lt;br /&gt;     httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    String contentObj = "http://www.woot.com/salerss.aspx";&lt;br /&gt;       wootGet = new HttpGet(contentObj);&lt;br /&gt; }&lt;br /&gt;  &lt;br /&gt; &lt;br /&gt;   /**&lt;br /&gt;    * Processes requests for both HTTP &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; methods.&lt;br /&gt;    * @param request servlet request&lt;br /&gt;    * @param response servlet response&lt;br /&gt;    * @throws ServletException if a servlet-specific error occurs&lt;br /&gt;    * @throws IOException if an I/O error occurs&lt;br /&gt;    */&lt;br /&gt;   protected void processRequest(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;           throws ServletException, IOException {&lt;br /&gt;  &lt;br /&gt;  HttpResponse wootResponse = httpClient.execute(wootGet);&lt;br /&gt;      &lt;br /&gt;       HttpEntity wootEntity = wootResponse.getEntity();&lt;br /&gt;      &lt;br /&gt;       response.setContentType(wootEntity.getContentType().toString());&lt;br /&gt;       // Get and read the input stream.&lt;br /&gt;       StringBuffer buffer = new StringBuffer();&lt;br /&gt;&lt;br /&gt;       BufferedReader din =&lt;br /&gt;                      new BufferedReader(new InputStreamReader(wootEntity.getContent()));&lt;br /&gt;&lt;br /&gt;       String s;&lt;br /&gt;       while ((s = din.readLine()) != null) {&lt;br /&gt;           buffer.append(s);&lt;br /&gt;       }&lt;br /&gt;       din.close();&lt;br /&gt;&lt;br /&gt;       // Now write the bytes out to the client.&lt;br /&gt;       byte[] contentBytes = buffer.toString().getBytes();&lt;br /&gt;       OutputStream out = response.getOutputStream();&lt;br /&gt;       out.write(contentBytes, 0, contentBytes.length);&lt;br /&gt;       out.flush();&lt;br /&gt;       out.close();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * Handles the HTTP &lt;code&gt;GET&lt;/code&gt; method.&lt;br /&gt;    * @param request servlet request&lt;br /&gt;    * @param response servlet response&lt;br /&gt;    * @throws ServletException if a servlet-specific error occurs&lt;br /&gt;    * @throws IOException if an I/O error occurs&lt;br /&gt;    */&lt;br /&gt;   @Override&lt;br /&gt;   protected void doGet(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;           throws ServletException, IOException {&lt;br /&gt;       processRequest(request, response);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * Handles the HTTP &lt;code&gt;POST&lt;/code&gt; method.&lt;br /&gt;    * @param request servlet request&lt;br /&gt;    * @param response servlet response&lt;br /&gt;    * @throws ServletException if a servlet-specific error occurs&lt;br /&gt;    * @throws IOException if an I/O error occurs&lt;br /&gt;    */&lt;br /&gt;   @Override&lt;br /&gt;   protected void doPost(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;           throws ServletException, IOException {&lt;br /&gt;       processRequest(request, response);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * Returns a short description of the servlet.&lt;br /&gt;    * @return a String containing servlet description&lt;br /&gt;    */&lt;br /&gt;   @Override&lt;br /&gt;   public String getServletInfo() {&lt;br /&gt;       return "Woot Tracker Proxy";&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The code has changed to setup the client once and initialize it once.  Additionally, there is the code provided by the HttpClient project that adds a proxy to the client.  One additional change needs to be the ability to track a &lt;a href="http://kids.woot.com/"&gt;Kids.Woot-Off&lt;/a&gt; URL in case it's a different kind of woot-off.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The HTML/Javascript remains the same.  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-7738363552401046955?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/12tM5tq3dDbno0vjb11HznRtRSk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/12tM5tq3dDbno0vjb11HznRtRSk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/12tM5tq3dDbno0vjb11HznRtRSk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/12tM5tq3dDbno0vjb11HznRtRSk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=uP9LcVeClEQ:8qqA7hAd9Kg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=uP9LcVeClEQ:8qqA7hAd9Kg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=uP9LcVeClEQ:8qqA7hAd9Kg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=uP9LcVeClEQ:8qqA7hAd9Kg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=uP9LcVeClEQ:8qqA7hAd9Kg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=uP9LcVeClEQ:8qqA7hAd9Kg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=uP9LcVeClEQ:8qqA7hAd9Kg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=uP9LcVeClEQ:8qqA7hAd9Kg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/uP9LcVeClEQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/7738363552401046955/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=7738363552401046955" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7738363552401046955?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7738363552401046955?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/uP9LcVeClEQ/simple-web-tool-building-with-maven.html" title="Simple Web Tool Building With Maven (The Woot-Off Tracker Revisited)" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/11/simple-web-tool-building-with-maven.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UDSHo9fip7ImA9WxNbFEs.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-2206901165826323130</id><published>2009-10-30T14:25:00.007-04:00</published><updated>2009-11-17T09:47:59.466-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-17T09:47:59.466-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sonar" /><category scheme="http://www.blogger.com/atom/ns#" term="hudson" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Converting to the Ultimate Java Build Stack</title><content type="html">Over the past 6 months, I've had the pleasure and pain of working with Maven. Even with all of the pain, I've found myself a fan of the technology, assuming, of course, that you have the &lt;a href="http://juddsolutions.blogspot.com/2009/05/ultimate-enterprise-java-build-system.html"&gt;appropriate Maven stack&lt;/a&gt; set up.&lt;br /&gt;&lt;br /&gt;During my time at the client, I setup &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt;, &lt;a href="http://nexus.sonatype.org/"&gt;Nexus&lt;/a&gt;, and &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt; as outlined in Christopher Judd's blog post.  We had actually already decided upon Hudson and Nexus through discovery before Judd published his post.  Sonar was a nice discovery we added to the mix a bit later.  Having setup this stack, I thought I'd offer some thoughts on my experiences.&lt;br /&gt;&lt;br /&gt;I cannot stress how important having &lt;a href="http://repository.sonatype.org/index.html#welcome"&gt;Nexus&lt;/a&gt; (or Artifactory) is to keeping your Maven projects running smoothly and effectively. Having a repository management tool and proxy allows for all of your developers (and Hudsons) to simply point at the proxy and download everything required for a build quickly.  It also provides a place for you to host your third party jars from apps that have been purchased by your organization. Not everything is open source of course.&lt;br /&gt;&lt;br /&gt;The steps are simple enough, install Nexus and setup your settings.xml file to point to it.  For developers, they can use their own settings.xml file.  For Hudson, you may want to modify the settings.xml in your Maven install (especially if you're running on Windows).  You might need to add a mirror for Java.net's Maven 2 repository.  You might not.  It depends upon how up to date Maven's central repository is.&lt;br /&gt;&lt;br /&gt;Sonar was a nice surprise.  Providing PMD, Checkstyle and Cobertura results in a nice visual manner that allowed for quick feedback was surprisingly effective.  As a developer, I found it to be my favorite part of the switch to Maven.  Sure, Maven provides this information as part of its site goal, however, it doesn't present it like &lt;a href="http://nemo.sonar.codehaus.org/"&gt;this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Obviously there are huge gains to be made by integrating Hudson and getting it to build upon version control commits, but I found more intriguing was its ability to trigger downstream builds.  When I built the commons library for the app, every maven artifact that used the commons library was triggered for build.  Numerous times, I discovered that I or someone else had broken something in a downstream library due to an API fix.  That instant feedback (through RSS feeds) was an invaluable time saver.&lt;br /&gt;&lt;br /&gt;What about Maven itself?  What does it gain you?  In the case I was working on, tremendous build granularity.  The original build used Ant, and was built in a monolithic manner.  Each component was built by the single script and bundled together.  One could argue it wasn't the best ant script in the world, and they'd be right.  Maven allowed us to break these dependencies apart.  So now, instead of having one monolithic code base which included what were really five separate artifacts, we now had five separate projects, each self contained using dependencies to draw in the needed artifacts.  As such the WAR and EAR builds ended up being very simple where they just drew in their needed dependencies and just worked.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Additionally, Maven offered unit testing at a very cheap cost.  The initial code base had no unit testing.  The developers were keen to use the debugger to test scenarios, which is needed to understand the mass amounts of reflection which were in use.  However, that's only helpful in understanding the code.  There should have been unit tests which were stood up to test each component on its own.  Maven automagically gives you unit testing with the surefire plugin enabled by default.  Make sure JUnit is a test dependency and start writing tests into the test source tree.  Keep your tests in the same package as your code and start gaining coverage. In between adding new features to the code base, I was able to increase code coverage on the base level components from 0 to 40%.  Obviously there's still a long way to go, but this was a vast improvement!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing I will note about Maven is the tooling.  There is tremendous tooling available in the m2eclipse plugin for Eclipse.  Netbeans 6.5 and above opens Maven projects without needing to do much of anything.  It just opens the directory containing the pom and imports the project.  If you're moving to Maven, make sure that your development tools can support it.  As an example, RAD 7.0.x is Eclipse 3.2.  As such the m2eclipse plugin does not work for it.  If you &lt;i&gt;must&lt;/i&gt; use RAD 7.0.x, I would advise building your project outside of RAD.  Use a more up to date IDE to get the projects started and structures built.  Then use the maven-eclipse-plugin to build the proper project eclipse artifacts for your projects.  It will still be a challenge to build proper EAR and WAR projects for RAD.  Maven has a lot of help for this sort of pain.  However it can only be applied if you use the proper tools.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've got a bit more to say about Maven, especially with my experiences of converting projects to Maven, the various pain and joy points I experienced and overall satisfaction.  But I'll leave that for another post.  Until then, I strongly suggest that if you have new development and you are looking for a pure Java based project build management tool, that you should take a long hard look at Maven.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-2206901165826323130?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2FMM_22ivVBe-A7FYk1dzyvuNU0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2FMM_22ivVBe-A7FYk1dzyvuNU0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2FMM_22ivVBe-A7FYk1dzyvuNU0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2FMM_22ivVBe-A7FYk1dzyvuNU0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=fY2CxLSTZfs:NUXCCDuqlC4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=fY2CxLSTZfs:NUXCCDuqlC4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=fY2CxLSTZfs:NUXCCDuqlC4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=fY2CxLSTZfs:NUXCCDuqlC4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=fY2CxLSTZfs:NUXCCDuqlC4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=fY2CxLSTZfs:NUXCCDuqlC4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=fY2CxLSTZfs:NUXCCDuqlC4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=fY2CxLSTZfs:NUXCCDuqlC4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/fY2CxLSTZfs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/2206901165826323130/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=2206901165826323130" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2206901165826323130?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2206901165826323130?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/fY2CxLSTZfs/converting-to-ultimate-java-build-stack.html" title="Converting to the Ultimate Java Build Stack" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/10/converting-to-ultimate-java-build-stack.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UBRn04fCp7ImA9WxNbFEs.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-751340390698967839</id><published>2009-09-14T16:40:00.008-04:00</published><updated>2009-11-17T09:47:37.334-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-17T09:47:37.334-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="site-deploy" /><category scheme="http://www.blogger.com/atom/ns#" term="hudson" /><category scheme="http://www.blogger.com/atom/ns#" term="maven" /><title>Wierdness with Maven's site-deploy and Hudson</title><content type="html">&lt;p&gt;So, for the past five months or so, I've been working on porting some Java projects to Maven and the &lt;a href="http://juddsolutions.blogspot.com/2009/05/ultimate-enterprise-java-build-system.html"&gt;Ultimate Enterprise Java Build System&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A quick aside, Sonar is a very underrated tool.  You should try it.  I find the reporting very easy to use and very handy for working through potential coding mistakes in the legacy code I've been working with.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;One of those Java projects is a large multi-module Maven build.  It has five different modules, three Jar modules, a War module and *gasp* an Ear module.  It's been a bit of a beast to get going, but it seems to be working just fine.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;On Monday, I began to perform releases to move from Maven SNAPSHOTs to actual real version numbers.  Ah, the joys of SCM release management.  Thankfully, all of this pain ends up being worth it to easily tag and lock the code down using the &lt;a href="http://maven.apache.org/plugins/maven-release-plugin/"&gt;maven-release-plugin&lt;/a&gt;.  There were a couple of bumps, but it wasn't bad.&lt;/p&gt;&lt;p&gt;The fun began when I built my Hudson jobs to perform release builds.  These jobs simply pulled the tagged release and performed the following goals:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;clean install site-deploy&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Obviously, I used Hudson's deploy step for the artifacts rather than Maven's.  And everything was fine, until I got this:&lt;/p&gt;&lt;br /&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[ERROR] BUILD ERROR&lt;br /&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[INFO] Failed to resolve artifact.&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Oops, what's that about?  A little more background.  This particular maven build was a multimodule build to create jar, war and ear files.  The artifact it couldn't resolve was the first jar it built! Scanning the log file, it became clear that the job was not installing the built jar to the repository.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I don't know why that is, and am not certain if it's even worth opening a trouble ticket since the fix ended up being very simple.  It seems that site-deploy was causing issues with the flow of the job within Hudson.  By removing site-deploy the build ended up being successful.  The jar was compiled, tested and installed before the next module's build was invoked.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I still wanted to build the site, so I investigated the &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/M2+Extra+Steps+Plugin"&gt;M2 Extra Steps Plugin&lt;/a&gt;. This tool allows you to add multiple maven steps before and after the main job.  I added the site-deploy goal to run after the main install goal and the sites were generated!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-751340390698967839?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4p9VbIgyefKa2HvHi62SEgq_ZlQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4p9VbIgyefKa2HvHi62SEgq_ZlQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4p9VbIgyefKa2HvHi62SEgq_ZlQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4p9VbIgyefKa2HvHi62SEgq_ZlQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=TEWTFGgF1-I:0E75pjqjTIE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=TEWTFGgF1-I:0E75pjqjTIE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=TEWTFGgF1-I:0E75pjqjTIE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=TEWTFGgF1-I:0E75pjqjTIE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=TEWTFGgF1-I:0E75pjqjTIE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=TEWTFGgF1-I:0E75pjqjTIE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=TEWTFGgF1-I:0E75pjqjTIE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=TEWTFGgF1-I:0E75pjqjTIE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/TEWTFGgF1-I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/751340390698967839/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=751340390698967839" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/751340390698967839?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/751340390698967839?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/TEWTFGgF1-I/wierdness-with-mavens-site-deploy-and.html" title="Wierdness with Maven's site-deploy and Hudson" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/09/wierdness-with-mavens-site-deploy-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkENRX09eCp7ImA9WxJbF00.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-7156566614455461370</id><published>2009-07-27T09:16:00.002-04:00</published><updated>2009-07-27T09:18:14.360-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-27T09:18:14.360-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>Trexma for Firefox 3.5</title><content type="html">Been away from the blogging world for a while.  Been away from the Trexma world for a while.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;During that time, Firefox 3.5 was released and I hadn't had the opportunity to change a simple setting and redeploy the package for 3.5.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well that's been done now.  You can now download Trexma 0.8.5.1 from the &lt;a href="http://code.google.com/p/trexma-for-firefox/"&gt;google code site&lt;/a&gt;.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully this helps. :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-7156566614455461370?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/keLjXOx38czzMXbpEuVDyiPUoSg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/keLjXOx38czzMXbpEuVDyiPUoSg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/keLjXOx38czzMXbpEuVDyiPUoSg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/keLjXOx38czzMXbpEuVDyiPUoSg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=QLiiq0mw7jM:SrK5or_ZbVI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=QLiiq0mw7jM:SrK5or_ZbVI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=QLiiq0mw7jM:SrK5or_ZbVI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=QLiiq0mw7jM:SrK5or_ZbVI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=QLiiq0mw7jM:SrK5or_ZbVI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=QLiiq0mw7jM:SrK5or_ZbVI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TwoFourOne?a=QLiiq0mw7jM:SrK5or_ZbVI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TwoFourOne?i=QLiiq0mw7jM:SrK5or_ZbVI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/QLiiq0mw7jM" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="Trexma for Firefox 3.5" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/7156566614455461370/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=7156566614455461370" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7156566614455461370?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7156566614455461370?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/QLiiq0mw7jM/trexma-for-firefox-35.html" title="Trexma for Firefox 3.5" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/07/trexma-for-firefox-35.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YAR3syeip7ImA9WxVXE00.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-1165984268683622771</id><published>2009-02-10T15:57:00.008-05:00</published><updated>2009-02-10T16:25:46.592-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-10T16:25:46.592-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="US Mexico" /><category scheme="http://www.blogger.com/atom/ns#" term="US Soccer" /><title>US Mexico Tomorrow (the Mexi-whore edition)</title><content type="html">Going to go away from programming and into hijinks mode for a moment.  Too many memories coming back from eight years ago during the epic 2001 battle between the US and Mexico in Columbus.&lt;br /&gt;&lt;br /&gt;As with most big sporting events that actually allow in the inebriated public, the stands can be an interesting place.  I stood in about 2 rows from the top of the North End, directly behind the goal.  It was from this angle that I was able to see some mighty entertaining things.&lt;br /&gt;&lt;br /&gt;The first was the Mexi-whore.  Someone, obviously during a highly energetic brainstorming session fueled by Jager or Firewater, decided to purchase an adult doll.  You know the kind of doll I'm talking about.  The owner then acquired an undergarment for the doll, a thong of some nature, as well as a Mexican jersey.  At various times during the match, the doll was held aloft by a leg while a cohort proceeded to spank the doll.&lt;br /&gt;&lt;br /&gt;Needless to say, the presence of this doll has reached legendary status.  But today I have found proof! In this snap from YouTube, you can see the head of the doll circled.  It did exist.  I can only hope it will make a return.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_TxqtW3PNwtM/SZHtvvuaNNI/AAAAAAAABio/h9ewTDDGGk4/s1600-h/mexiwhore.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 266px;" src="http://4.bp.blogspot.com/_TxqtW3PNwtM/SZHtvvuaNNI/AAAAAAAABio/h9ewTDDGGk4/s400/mexiwhore.JPG" alt="" id="BLOGGER_PHOTO_ID_5301279640912540882" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Other entertaining items were the signs.  This sign would not made it through today's PC filters.  The text of it read: Red Card, Yellow Card, Mexican&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_TxqtW3PNwtM/SZHwK_KVbxI/AAAAAAAABiw/9g4XWr5i0zg/s1600-h/mexicancard.JPG"&gt;&lt;img style="cursor: pointer; width: 400px; height: 261px;" src="http://4.bp.blogspot.com/_TxqtW3PNwtM/SZHwK_KVbxI/AAAAAAAABiw/9g4XWr5i0zg/s400/mexicancard.JPG" alt="" id="BLOGGER_PHOTO_ID_5301282307935923986" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Yep, definitely wouldn't be "allowed" today.  It also shows you how different things were eight years ago.  Most everyone had a good time...some had too much of one.  There was that one drunken guy who thought it would be a good idea to take taunting to the next level and to moon a bunch of Mexican fans in the parking lot.  It might have been harmless had their not been a slew of vulgarity and elementary school kids in the car.  Needless to say, he almost got his ass kicked.&lt;br /&gt;&lt;br /&gt;The full YouTube video for your enjoyment:&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/XdUGy--8-Pc&amp;amp;hl=en&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/XdUGy--8-Pc&amp;amp;hl=en&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;At any rate, the hijinks tomorrow should be outstanding.  If you're attending, I hope to see you there.  If you're watching at home, hopefully you'll see some antics on TV or YouTube in the days to come.  I'm hoping for a big US win, in the slop and wind that will be Columbus Crew Stadium.  And maybe the return of the Mexi-whore.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-1165984268683622771?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/EsNnwCiZ63F7OocDUZ_hWE0TH4Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EsNnwCiZ63F7OocDUZ_hWE0TH4Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/EsNnwCiZ63F7OocDUZ_hWE0TH4Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EsNnwCiZ63F7OocDUZ_hWE0TH4Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=cInO2RJ5"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=bKYP4wvR"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=y79VIy4k"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=y79VIy4k" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=pltTA7Ur"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=pltTA7Ur" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=niSfh3je"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=niSfh3je" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/B0vqjoGT7p4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/1165984268683622771/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=1165984268683622771" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1165984268683622771?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1165984268683622771?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/B0vqjoGT7p4/us-mexico-tomorrow-mexi-whore-edition.html" title="US Mexico Tomorrow (the Mexi-whore edition)" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_TxqtW3PNwtM/SZHtvvuaNNI/AAAAAAAABio/h9ewTDDGGk4/s72-c/mexiwhore.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/02/us-mexico-tomorrow-mexi-whore-edition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEMSHY9eSp7ImA9WxVQE0g.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-7776313950814109255</id><published>2009-01-30T16:22:00.001-05:00</published><updated>2009-01-30T16:24:49.861-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-30T16:24:49.861-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>TrExMa 0.8.5 is out</title><content type="html">TrExMa 0.8.5 is &lt;a href="http://code.google.com/p/trexma-for-firefox/"&gt;released&lt;/a&gt;.  This includes a bunch of code cleanup, removal of the old quick lineup in favor of the complete Hungarian Algorithm method as well as converting the Shortlist, and Youth Development to use the new codebase.&lt;br /&gt;&lt;br /&gt;If all goes well, this could be the final "preview" before deprecating 0.6.2.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-7776313950814109255?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hg7RhtATLnPg1WW7vPjep6UoTrU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hg7RhtATLnPg1WW7vPjep6UoTrU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hg7RhtATLnPg1WW7vPjep6UoTrU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hg7RhtATLnPg1WW7vPjep6UoTrU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=ljFgIgBp"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=1uApAT3q"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=0NKaWBKk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=0NKaWBKk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=csrv1sSB"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=csrv1sSB" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=lLy3O686"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=lLy3O686" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/daki5PhcboA" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="TrExMa 0.8.5 is out" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/7776313950814109255/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=7776313950814109255" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7776313950814109255?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7776313950814109255?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/daki5PhcboA/trexma-085-is-out.html" title="TrExMa 0.8.5 is out" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/01/trexma-085-is-out.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAGR3k-eCp7ImA9WxVRFks.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-5722192884309185557</id><published>2009-01-22T16:41:00.006-05:00</published><updated>2009-01-22T17:18:46.750-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-22T17:18:46.750-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="Hungarian Algorithm" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>The Hungarian Algorithm in Javascript</title><content type="html">For the past 7 months or so, I've been dabbling in XUL/Javascript as evidenced by the posts you can find on here about TrophyManager.com and the TrExMa plugin I created for the game.&lt;br /&gt;&lt;br /&gt;Recently, I got to tackle an old school problem.  Only I didn't know it was old school at the time when I started.  I suppose that's because I've not been doing hardcore Computer Science type problems in quite some time.&lt;br /&gt;&lt;br /&gt;Here's the problem:  In TrophyManager, you field a soccer team of 11 players, 10 field players and a keeper.  TrExMa calculates a skill for each player on your roster to try to give the user an idea of what the best possible lineup would be.  Selecting the keeper is easy.  Take the guy with the highest value.  Selecting the field players, not so much.&lt;br /&gt;&lt;br /&gt;Each player has 14 "visible" attributes.  Early players of the game used the instruction manual to determine which attribute is most important for the position the player is in.  For example, a Forward must be good at Finishing and Heading, etc.  Additionally, each player has a favorite position.  When they play "away" from their position, their skill drops.  So a player may have a high finishing skill, but since they like to play left back, they're not going to be a very good striker and would have their skill reduced anywhere from 4-40% depending upon a hidden adaptability attribute.&lt;br /&gt;&lt;br /&gt;Anyway, how does one figure out the best team?  I can set the adaptablity factor from 1-10% and we can then caclulate the skill for every position on the field for every player on the team.  Sounds good, right?  But how to pick it?&lt;br /&gt;&lt;br /&gt;I first looked at the original TrExMa algorithm within Excel.  The original app had a drop down to determine the depth of the search.  Once I looked at the code it was confirmed.  TrExMa used a series of nested loops to build the lineup.  If I'm not mistaken it could run from O(n^5) to O(n^10) depending upon the complexity you chose.  Wow, no wonder it got very slow.  I needed something else.  I also realized that the only way this algorithm would guaruntee success would be to run it at O(n^10) setting.  Using Javascript, this was simply unacceptable.  I couldn't get away with something running for so long.&lt;br /&gt;&lt;br /&gt;My first instinct was to use an algorithm similar to &lt;a href="http://en.wikipedia.org/wiki/Bin_packing_problem"&gt;Fit First&lt;/a&gt;.  In this case, find the highest value on the board, and place the player there.  cross him out and cross out the position.  Do it again until you've filled the positions.  Supposedly this runs in O(n log n). Of course, 10 is pretty small for me, as I've only 10 boxes to fill.  It's pretty good, but doesn't guaruntee the best match of players to positions.  Why?  Let's say you've got a player who is adept at a midfield and wing position.  And another player who is only good at midfield.  If the former is slightly better at midfield, he'll be placed there, and the other player will have to play somewhere else where he won't be as successful.&lt;br /&gt;&lt;br /&gt;How do you correct this?  I soon realized that this had to be a common problem, I just couldn't figure out what to call it?  Eventually I discovered that it's known as an "&lt;a href="http://en.wikipedia.org/wiki/Assignment_problem"&gt;assignment problem&lt;/a&gt;". It's an obvious name, now that I know what it is.  The classical use of this problem is to determine the least overall cost of doing multiple things with multiple resources.  It's very similar.&lt;br /&gt;&lt;br /&gt;Soon I discovered the &lt;a href="http://en.wikipedia.org/wiki/Hungarian_algorithm"&gt;Hungarian Algorithm&lt;/a&gt;.  It runs in O(n^4) (potentially O(n^3)).  So it's not fast, but it's not insanely slow.  It's not exponential, and it runs faster than the Excel app.&lt;br /&gt;&lt;br /&gt;So what does the Hungarian Algorithm do?  It uses a method of &lt;span style="font-style: italic;"&gt;starring &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;priming &lt;/span&gt;to determine when a player is in its ideal place.  Essentially, if two players are "best" at a position, it will not accept that assignment until it validates the best organization of those players.  It's explained very well in the Wikipedia page.&lt;br /&gt;&lt;br /&gt;There are many implementations of the Hungarian Algorithm on the net but none in Javascript.  So here's one.  I've pulled out some of the specifics for my implementation.  You'll want to implement your own loadMatrix and getSolution methods.  One thing to note, is that with my problem, we had to reverse the matrix.  This is required because the Hungarian Algorithm uses small values to determine the best player (worker) for a position (job).  I hope you find this useful.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;/* Implementation of the Hungarian Algorithm to determine&lt;br /&gt;* "best" squad.  This is a "reverse" implementation.&lt;br /&gt;* References:&lt;br /&gt;* http://en.wikipedia.org/wiki/Hungarian_algorithm&lt;br /&gt;* http://www.ams.jhu.edu/~castello/362/Handouts/hungarian.pdf (Example #2)&lt;br /&gt;* http://www.public.iastate.edu/~ddoty/HungarianAlgorithm.html // Non-square&lt;br /&gt;*/&lt;br /&gt;var Hungarian = window.Hungarian = window.HG = {&lt;br /&gt;&lt;br /&gt; /* 2 dimension arrays */&lt;br /&gt; skillMatrix: null,&lt;br /&gt; matrix: null,&lt;br /&gt; stars: null,&lt;br /&gt; /* Single arrays */&lt;br /&gt; rCov: [],&lt;br /&gt; cCov: [],&lt;br /&gt; rows: 0,&lt;br /&gt; cols: 0,&lt;br /&gt; dim: 0,&lt;br /&gt; solutions: 0, // "k"&lt;br /&gt; FORBIDDEN_VALUE: -999999,&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; /* Rows MUST BE the Formation (Jobs)&lt;br /&gt;  * Columns MUST BE the Squad (Workers)&lt;br /&gt;  * Therefore, the Rows MUST BE PADDED&lt;br /&gt;  */&lt;br /&gt; hungarianAlgortithm: function(formation, squad) {&lt;br /&gt;   HG.init(formation, squad);&lt;br /&gt;   // Step 1&lt;br /&gt;   HG.matrix = HG.subtractRowMins(HG.matrix);&lt;br /&gt;   // Step 2&lt;br /&gt;   HG.findZeros(HG.matrix);&lt;br /&gt;   var done = false;&lt;br /&gt;   while (!done) {&lt;br /&gt;     // Step 3&lt;br /&gt;     var covCols = HG.coverColumns(HG.matrix);&lt;br /&gt;     if (covCols &amp;gt; HG.solutions -1) {&lt;br /&gt;       done = true;&lt;br /&gt;     }&lt;br /&gt;     if (!done) {&lt;br /&gt;    // Step 4 (calls Step 5)&lt;br /&gt;       done = HG.coverZeros(HG.matrix);&lt;br /&gt;       while (done) {&lt;br /&gt;         // Step 6&lt;br /&gt;         var smallest = HG.findSmallestUncoveredVal(HG.matrix);&lt;br /&gt;         HG.matrix = HG.uncoverSmallest(smallest, HG.matrix);&lt;br /&gt;         done = HG.coverZeros(HG.matrix);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return HG.getSolution(formation, squad)&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; init: function(formation, squad) {&lt;br /&gt;   HG.cols = squad.players.length;&lt;br /&gt;   HG.rows = formation.length;&lt;br /&gt;   HG.dim = Math.max(HG.rows, HG.cols);&lt;br /&gt;   HG.solutions = HG.dim;&lt;br /&gt;   HG.skillMatrix = HG.initMatrix(HG.rows, HG.cols);&lt;br /&gt;   HG.matrix = HG.initMatrix(HG.dim, HG.dim);&lt;br /&gt;   HG.stars = HG.initMatrix(HG.dim, HG.dim);&lt;br /&gt;   HG.matrix = HG.loadMatrix(squad, formation, HG.matrix, true);&lt;br /&gt;   HG.skillMatrix = HG.loadMatrix(squad, formation, HG.skillMatrix, false);&lt;br /&gt;&lt;br /&gt;   HG.rCov = new Array(HG.dim);&lt;br /&gt;   HG.cCov = new Array(HG.dim);&lt;br /&gt;   HG.initArray(HG.cCov, 0); // Zero it out&lt;br /&gt;   HG.initArray(HG.rCov, 0);&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; initMatrix: function(sizeX, sizeY) {&lt;br /&gt;   var matrix = new Array(sizeX);&lt;br /&gt;   for (var i=0; i&amp;lt;sizeX; i++) {&lt;br /&gt;     matrix[i] = new Array(sizeY);&lt;br /&gt;     HG.initArray(matrix[i], 0);&lt;br /&gt;   }&lt;br /&gt;   return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; // Takes an array of positions as a formation.&lt;br /&gt; // Takes a squad which contains an array of players&lt;br /&gt; loadMatrix: function(squad, formation, matrix, reverse) {&lt;br /&gt;   matrix = loadYourMatrix(squad, formation, matrix); // I've removed my implementation here. Far too much stuff&lt;br /&gt;   if (reverse) {&lt;br /&gt;   // This reverses the matrix.  We need to to create a cost based solution.&lt;br /&gt;     matrix = HG.reverseMatrix(HG.findMaxValue(matrix), matrix);&lt;br /&gt;   }&lt;br /&gt;   return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findMaxValue: function(matrix) {&lt;br /&gt;   var max = 0.0;&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i ++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (matrix[i][j] &amp;gt; max) {&lt;br /&gt;         max = matrix[i][j];&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return Number(max);&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; reverseMatrix: function(max, matrix) {&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i ++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       matrix[i][j] = (Number(max) - Number(matrix[i][j])).toFixed(0);&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; subtractRowMins: function(matrix) {&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i ++) {&lt;br /&gt;     var min = Number.MAX_VALUE;&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (matrix[i][j] &amp;lt; min) {&lt;br /&gt;         min = Number(matrix[i][j]);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;     for (var k = 0; k &amp;lt; matrix[i].length; k++) {&lt;br /&gt;       matrix[i][k] = matrix[i][k] - min;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;  return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; subtractColMins: function(matrix) {&lt;br /&gt;   for (var j = 0; j &amp;lt; matrix[0].length; j ++) {&lt;br /&gt;     var min = Number.MAX_VALUE;&lt;br /&gt;     for (var i = 0; i &amp;lt; matrix.length; i++) {&lt;br /&gt;       if (matrix[i][j] &amp;lt; min) {&lt;br /&gt;         min = Number(matrix[i][j]);&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;     for (var k = 0; k &amp;lt; matrix[0].length; k++) {&lt;br /&gt;       matrix[k][j] = matrix[k][j] - min;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findZeros: function(matrix) {&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (matrix[i][j] == 0) {&lt;br /&gt;         if (HG.rCov[i] == 0 &amp;amp;&amp;amp; HG.cCov[j] == 0) {&lt;br /&gt;           HG.stars[i][j] = 1;&lt;br /&gt;           HG.cCov[j] = 1;&lt;br /&gt;           HG.rCov[i] = 1;&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   // Clear Covers&lt;br /&gt;   HG.initArray(HG.cCov,0);&lt;br /&gt;   HG.initArray(HG.rCov,0);&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; initArray: function(theArray, initVal) {&lt;br /&gt;   for (var i = 0; i &amp;lt; theArray.length; i++) {&lt;br /&gt;     theArray[i] = Number(initVal);&lt;br /&gt;   }&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; coverColumns: function(matrix) {&lt;br /&gt;   var count = 0;&lt;br /&gt;   for (var i=0; i &amp;lt; matrix.length; i++) {&lt;br /&gt;     for (var j=0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (HG.stars[i][j] == 1) {&lt;br /&gt;         HG.cCov[j] = 1;&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   for (var k=0; k &amp;lt; HG.cCov.length; k++) {&lt;br /&gt;     count = Number(HG.cCov[k]) + Number(count);&lt;br /&gt;   }&lt;br /&gt;   return count;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * step 4&lt;br /&gt;  * Cover all the uncovered zeros one by one until no more&lt;br /&gt;  * cover the row and uncover the column&lt;br /&gt;  */&lt;br /&gt; coverZeros: function(matrix) {&lt;br /&gt;   var retVal = true;&lt;br /&gt;  var zero = HG.findUncoveredZero(matrix); // Returns a Coords object..&lt;br /&gt;  &lt;br /&gt;   while (zero.row &amp;gt; -1 &amp;amp;&amp;amp; retVal == true) {&lt;br /&gt;     HG.stars[zero.row][zero.col] = 2 //Prime it&lt;br /&gt;     var starCol = HG.foundStarInRow(zero.row, matrix);&lt;br /&gt;     if (starCol &amp;gt; -1) {&lt;br /&gt;       HG.rCov[zero.row] = 1;&lt;br /&gt;       HG.cCov[starCol] = 0;&lt;br /&gt;     } else {&lt;br /&gt;       HG.starZeroInRow(zero); // Step 5&lt;br /&gt;       retVal = false;&lt;br /&gt;     }&lt;br /&gt;     if (retVal == true) {&lt;br /&gt;       zero = HG.findUncoveredZero(matrix);&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return retVal;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findUncoveredZero: function(matrix) {&lt;br /&gt;   var coords = new HgCoords();&lt;br /&gt;   for (var i=0; i&amp;lt; matrix.length; i++) {&lt;br /&gt;     for (var j=0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (matrix[i][j] == 0 &amp;amp;&amp;amp; HG.rCov[i] == 0 &amp;amp;&amp;amp; HG.cCov[j] == 0) {&lt;br /&gt;         coords.row = i;&lt;br /&gt;         coords.col = j;&lt;br /&gt;         j = matrix[i].length;&lt;br /&gt;         i = matrix.length - 1;&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;   return coords;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; foundStarInRow: function(zeroRow, matrix) {&lt;br /&gt;   var retVal = -1;&lt;br /&gt;   for (var j = 0; j &amp;lt; matrix[zeroRow].length; j++) {&lt;br /&gt;     if (HG.stars[zeroRow][j] == 1) {&lt;br /&gt;       retVal = j;&lt;br /&gt;       j = matrix[zeroRow].length;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return retVal;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * step 5&lt;br /&gt;  * augmenting path algorithm&lt;br /&gt;  * go back to step 3&lt;br /&gt;  */&lt;br /&gt; starZeroInRow: function(zero) { // Takes a Coords Object&lt;br /&gt;   TrU.log("Step 5: Uncovered Zero:" + zero.row + "," + zero.col, TrU.DEBUG );&lt;br /&gt;   var done = false;&lt;br /&gt;   var count = 0;&lt;br /&gt;   var path = HG.initMatrix(HG.dim*2, 2);&lt;br /&gt;&lt;br /&gt;   path[count][0] = zero.row;&lt;br /&gt;   path[count][1] = zero.col;&lt;br /&gt;   while (!done) {&lt;br /&gt;     var row = HG.findStarInCol(path[count][1]);&lt;br /&gt;     if (row &amp;gt; -1) {&lt;br /&gt;       count++;&lt;br /&gt;       path[count][0] = row;&lt;br /&gt;       path[count][1] = path[count - 1][1];&lt;br /&gt;     } else {&lt;br /&gt;       done = true;&lt;br /&gt;      &lt;br /&gt;     }&lt;br /&gt;     if (!done) {&lt;br /&gt;       var col = HG.findPrimeInRow(path[count][0]);&lt;br /&gt;       count++;&lt;br /&gt;       path[count][0] = path[count - 1][0];&lt;br /&gt;       path[count][1] = col;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   HG.convertPath(path, count);&lt;br /&gt;&lt;br /&gt;   // Clear Covers&lt;br /&gt;   HG.initArray(HG.cCov,0);&lt;br /&gt;   HG.initArray(HG.rCov,0);&lt;br /&gt;   HG.erasePrimes();&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findStarInCol: function(col) {&lt;br /&gt;   var retVal = -1;&lt;br /&gt;   for (var i = 0; i &amp;lt; HG.stars.length; i++) {&lt;br /&gt;     if (HG.stars[i][col] == 1) {&lt;br /&gt;       retVal = i;&lt;br /&gt;       i = HG.stars.length;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return retVal;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findPrimeInRow: function(row) {&lt;br /&gt;   var retVal = -1;&lt;br /&gt;   for (var j=0; j&amp;lt; HG.stars[row].length; j++) {&lt;br /&gt;     if (HG.stars[row][j] == 2) {&lt;br /&gt;       retVal = j;&lt;br /&gt;       j = HG.stars[row].length;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return retVal;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; /* Should convert all primes to stars and reset all stars.&lt;br /&gt;  * Count is needed to be sure we look at all items in the path&lt;br /&gt;  */&lt;br /&gt; convertPath: function(path, count) {&lt;br /&gt;   HG.logMatrix(path, "Step 5: Converting Path.  Count = " + count);&lt;br /&gt;   for (var i=0; i &amp;lt; count+1; i++) {&lt;br /&gt;     var x = path[i][0];&lt;br /&gt;     var y = path[i][1];&lt;br /&gt;     if (HG.stars[x][y] == 1) {&lt;br /&gt;       HG.stars[x][y] = 0;&lt;br /&gt;     } else if (HG.stars[x][y] == 2) {&lt;br /&gt;       HG.stars[x][y] = 1;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; erasePrimes: function() {&lt;br /&gt;   for (var i=0; i&amp;lt;HG.stars.length; i++) {&lt;br /&gt;     for (var j=0; j &amp;lt; HG.stars[i].length; j++){&lt;br /&gt;       if (HG.stars[i][j] == 2) {&lt;br /&gt;         HG.stars[i][j] = 0;&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; findSmallestUncoveredVal: function(matrix) {&lt;br /&gt;   var min = Number.MAX_VALUE;&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (HG.rCov[i] == 0 &amp;amp;&amp;amp; HG.cCov[j] == 0) {&lt;br /&gt;         if (min &amp;gt; matrix[i][j]) {&lt;br /&gt;           min = matrix[i][j];&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return min;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * step 6&lt;br /&gt;  * modify the matrix&lt;br /&gt;  * if the row is covered, add the smallest value&lt;br /&gt;  * if the column is not covered, subtract the smallest value&lt;br /&gt;  */&lt;br /&gt; uncoverSmallest: function(smallest, matrix) {&lt;br /&gt;   TrU.log("Uncover Smallest: "+ smallest);&lt;br /&gt;       HG.logMatrix(matrix, "B4 Smallest uncovered");&lt;br /&gt;&lt;br /&gt;   for (var i = 0; i &amp;lt; matrix.length; i++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; matrix[i].length; j++) {&lt;br /&gt;       if (HG.rCov[i] == 1) {&lt;br /&gt;         matrix[i][j] += smallest;&lt;br /&gt;       }&lt;br /&gt;       if (HG.cCov[j] == 0) {&lt;br /&gt;         matrix[i][j] -= smallest;&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   HG.logMatrix(matrix, "Smallest uncovered");&lt;br /&gt;   return matrix;&lt;br /&gt; },&lt;br /&gt;&lt;br /&gt; getSolution: function(formation, squad) {&lt;br /&gt;   var total = 0;&lt;br /&gt;   var lineup = [];&lt;br /&gt;    // Changed from length of stars, since we must ignore some rows due to padding.&lt;br /&gt;   for (var i = 0; i &amp;lt; HG.rows; i++) {&lt;br /&gt;     for (var j = 0; j &amp;lt; HG.cols; j++) {&lt;br /&gt;       if (HG.stars[i][j] == 1) {&lt;br /&gt;     /* the player (worker) at index j is the best player&lt;br /&gt;      * for poisition (job) at index i in your initial arrays.&lt;br /&gt;      */&lt;br /&gt;         lineup.push(getThePlayer(i,j));&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return lineup;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function HgCoords() {&lt;br /&gt; this.row = -1;&lt;br /&gt; this.col = -1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-5722192884309185557?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0hS2XVoEGxbFYmv8fDpM5St69Q4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0hS2XVoEGxbFYmv8fDpM5St69Q4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0hS2XVoEGxbFYmv8fDpM5St69Q4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0hS2XVoEGxbFYmv8fDpM5St69Q4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=4NPezH8n"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=EncrBnDY"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=gtxc2bbM"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=gtxc2bbM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=96rfFEnN"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=96rfFEnN" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=qoFogB50"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=qoFogB50" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/A30UZN1_dLs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/5722192884309185557/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=5722192884309185557" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5722192884309185557?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5722192884309185557?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/A30UZN1_dLs/hungarian-algorithm-in-javascript.html" title="The Hungarian Algorithm in Javascript" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/01/hungarian-algorithm-in-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08HSX8-eyp7ImA9WxVSEko.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-1882139600430842149</id><published>2009-01-06T14:54:00.002-05:00</published><updated>2009-01-06T14:57:18.153-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-06T14:57:18.153-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>New TrExMa Preview Release</title><content type="html">I've updated TrExMa for Firefox after finding a bug in scraping the Transfer Pages.&lt;br /&gt;&lt;br /&gt;This bug exists in all versions of the plugin as the Transfer List uses slightly different HTML to display starred skills.  The starred skills were getting skipped over and treated as zero.  Sheffield FC also picked up on this bug and reported to me as I was in the midst of adding some additional features for this release.  So thanks to him for noticing the problem!&lt;br /&gt;&lt;br /&gt;Additional features include the introduction of skill summaries, Attack, Defending, etc.&lt;br /&gt;&lt;br /&gt;You can find the new plugin: http://code.google.com/p/trexma-for-firefox/&lt;br /&gt;&lt;br /&gt;Thanks!&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-1882139600430842149?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/l8_C0gfElNpphqBXtRs23Ub5BTI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l8_C0gfElNpphqBXtRs23Ub5BTI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/l8_C0gfElNpphqBXtRs23Ub5BTI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/l8_C0gfElNpphqBXtRs23Ub5BTI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=rEVEHzL6"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=5yMTJ9FM"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Tf3dVsAf"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=Tf3dVsAf" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Si40EINc"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=Si40EINc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=2DILe3P3"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=2DILe3P3" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/-aJgeowLPXY" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="New TrExMa Preview Release" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/1882139600430842149/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=1882139600430842149" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1882139600430842149?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1882139600430842149?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/-aJgeowLPXY/new-trexma-preview-release.html" title="New TrExMa Preview Release" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2009/01/new-trexma-preview-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04GSX48fip7ImA9WxRaFU4.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-5859120607440228450</id><published>2008-12-17T13:39:00.003-05:00</published><updated>2008-12-17T13:52:08.076-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-17T13:52:08.076-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>TrExMa for Firefox 0.8 Preview Release</title><content type="html">Over at &lt;a href="http://code.google.com/p/trexma-for-firefox/"&gt;TrExMa For Firefox&lt;/a&gt;, you can find a long awaited update to the TrExMa plugin for the popular TrophyManager game.  Version 0.8 is available and this is a Preview Release.&lt;br /&gt;&lt;br /&gt;This was an excuse to learn a little about &lt;a href="http://www.mozilla.org/projects/xul/"&gt;XUL&lt;/a&gt;, do some jQuery and refactor the plugin.  Unfortunately, it still needs a ton of refactoring, and the code is quite soupy.  This is a use at your own risk version.  The plugin can crash, provide a little popup saying something's wrong, and sometimes not even offer that.  It's buggy.  Since I'm not a XUL or UI expert, there's a lot of things that have been done in a sloppy fashion and things that cause bugs.  Anyone who's using this, I would really appreciate using the &lt;a href="http://code.google.com/p/trexma-for-firefox/issues/list"&gt;issue tracker&lt;/a&gt; rather than sending an email over at TM or posting in those forums.  Reason is, I get notified if someone posts an issue. &lt;br /&gt;&lt;br /&gt;It allows the user to see hit players abilities for all positions and dynamically change the loss of skill for the player being out of a favorite position.  This feature works by clicking on the TrExMa for Firefox label in the status bar.  You'll see a little XUL window appear in your browser.  If you browse to a squad screen or a transfer list screen, you'll get a list of players to choose from.  Clicking on a player will present the skills for that player in all positions available. &lt;br /&gt;&lt;br /&gt;In addition, a drop down box is available to determine what player is the best at each position.  If you want to find the best ML, select ML and the plugin will produce the top 5 players on that screen in that particular position.&lt;br /&gt;&lt;br /&gt;Quite a bit of refactoring involved brining in the &lt;a href="http://www.jquery.com"&gt;jQuery&lt;/a&gt; Javascript plugin.  I'm very happy with the integration of jQuery, it's an outstanding tool, as it just flat out works against HTML and XUL.&lt;br /&gt;&lt;br /&gt;If you don't like it, uninstall it and reinstall 0.6.2.  If you do like it, please offer suggestions and features that you'd like to see.  Still on the idea block is the ability to determine your best 11 for a given formation, but that's a little ways off.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-5859120607440228450?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UKv9O9ml9lwhg5WL-cyQSTLH1F4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UKv9O9ml9lwhg5WL-cyQSTLH1F4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UKv9O9ml9lwhg5WL-cyQSTLH1F4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UKv9O9ml9lwhg5WL-cyQSTLH1F4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=QkNIU1cH"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=PXsDxbck"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=7RzdQs9U"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=7RzdQs9U" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=GjcdxWgq"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=GjcdxWgq" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=o6ozJp7o"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=o6ozJp7o" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/oBJNs_dtpz8" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="TrExMa for Firefox 0.8 Preview Release" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/5859120607440228450/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=5859120607440228450" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5859120607440228450?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5859120607440228450?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/oBJNs_dtpz8/trexma-for-firefox-08-preview-release.html" title="TrExMa for Firefox 0.8 Preview Release" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/12/trexma-for-firefox-08-preview-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYFRHs8eyp7ImA9WxRbGEk.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-7707897604137869260</id><published>2008-12-09T12:00:00.007-05:00</published><updated>2008-12-09T12:35:15.573-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T12:35:15.573-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Woot-Off" /><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="Woot" /><category scheme="http://www.blogger.com/atom/ns#" term="Spry" /><title>A Spry Woot-Off Tracker</title><content type="html">Although &lt;a href="http://www.adobe.com/products/flex/"&gt;Flex&lt;/a&gt; is a neat tool, good ol' Javascript has been around for quite a while, and I thought I'd try to build a &lt;a href="http://www.woot.com"&gt;Woot-Off&lt;/a&gt; tracker using Flex's Javascript cousin, &lt;a href="http://labs.adobe.com/technologies/spry/home.html"&gt;Spry&lt;/a&gt;. Conveniently, there's a Woot-Off going on today.&lt;br /&gt;&lt;br /&gt;Spry is an interesting Javascript toolkit since it focuses on data extraction and presentation and widgets.  In this example, we're not using any widgets, but we are taking advantage of the Spry Dataset tools to grok the XML stream from Woot.  Just like with the AIR version, we need to use a proxy to grab the Woot XML stream.&lt;br /&gt;&lt;br /&gt;Spry's &lt;a href="http://labs.adobe.com/technologies/spry/articles/data_set_overview/index.html"&gt;DataSet&lt;/a&gt; works by allowing the developer to query the data set. Since Woot is providing an RSSish feed, we use the XMLDataSet class. By using braces, the dataset's contents can be accessed using the name of the XML tag.  So to grab the price, we use {woot:price}.  It's relatively simple.&lt;br /&gt;&lt;br /&gt;The challenging part is for data that's not quite perfectly formatted.  In this case, the percentage needs to be multiplied by 100.  We do that inside the &lt;a href="http://labs.adobe.com/technologies/spry/samples/data_region/DataSetObserver.html"&gt;Observer&lt;/a&gt;.  The Observer can update the contents of the dataset.  So you can simply create an observer function and change away.  The description also needs to be cleaned up since its HTML entities do not provide the needed effect.  We actually want to use the tags, so we unentify them.&lt;br /&gt;&lt;br /&gt;The timer is actually easier than in Flex, since the timer comes automatically with the DataSet with the loadInterval option.  The only thing we need to do is speed it up and slow it down at the appropriate time.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry"&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt; &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /&amp;gt;&lt;br /&gt; &amp;lt;title&amp;gt;Spry Woot Tracker&amp;lt;/title&amp;gt;&lt;br /&gt; &amp;lt;link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.6.0/build/reset-fonts-grids/reset-fonts-grids.css"/&amp;gt;&lt;br /&gt; &amp;lt;link href="css/wootTracker.css" rel="stylesheet" type="text/css" /&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript" src="includes/xpath.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript" src="includes/SpryData.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;   // we don't want to use cached data, and we need to reload every 30 seconds&lt;br /&gt;  var dsWootInfo = new Spry.Data.XMLDataSet("WootProxy", "rss/channel/item", {useCache: false, loadInterval: 30000});&lt;br /&gt;&lt;br /&gt;   var quickCheck = false; // Is the timer sped up&lt;br /&gt;&lt;br /&gt;   // Observer watches for when data changes and modifies for presentation&lt;br /&gt;   function wootObserver(notificationType, dataSet) {&lt;br /&gt;    if (notificationType == "onDataChanged") {&lt;br /&gt;       if (dataSet) {&lt;br /&gt;         var data = dataSet.getData();&lt;br /&gt;         var soldout = data[0]["woot:soldoutpercentage"];&lt;br /&gt;         data[0]["woot:soldoutpercentage"] = soldout*100;&lt;br /&gt;         var desc = data[0]["description"];&lt;br /&gt;         // Description contains HTML entities, fix them&lt;br /&gt;         // Something strange is going on with the formatter  it's just desc not descdesc&lt;br /&gt;         desc = desc.replace(/&amp;amp;gt;/g, "&amp;gt;");&lt;br /&gt;         desc = desc.replace(/&amp;amp;lt;/g, "&amp;lt;");&lt;br /&gt;         desc = desc.replace(/&amp;amp;quot;/g, '"');&lt;br /&gt;         desc = desc.replace(/[\u201C\u201d]/g, '"');&lt;br /&gt;         data[0]["description"] =  desc ;&lt;br /&gt;&lt;br /&gt;         // Determine if it's time to speed up or slow down&lt;br /&gt;         if (quickCheck) {&lt;br /&gt;           if (soldout &amp;lt; .95) {&lt;br /&gt;             dsWootInfo.stopLoadInterval();&lt;br /&gt;             dsWootInfo.startLoadInterval(30000);&lt;br /&gt;             quickCheck = false;&lt;br /&gt;           }&lt;br /&gt;         } else {&lt;br /&gt;           if (soldout &amp;gt; .95) {&lt;br /&gt;             dsWootInfo.stopLoadInterval();&lt;br /&gt;             dsWootInfo.startLoadInterval(1000);&lt;br /&gt;             quickCheck = true;&lt;br /&gt;           }&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;   dsWootInfo.addObserver(wootObserver);&lt;br /&gt;&lt;br /&gt; &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body id="wootTracker"&amp;gt;&lt;br /&gt; &amp;lt;noscript&amp;gt;&lt;br /&gt;  &amp;lt;h1&amp;gt;This page requires JavaScript. Please enable JavaScript in your browser and reload this page.&amp;lt;/h1&amp;gt;&lt;br /&gt; &amp;lt;/noscript&amp;gt;&lt;br /&gt; &amp;lt;div id="doc" spry:region="dsWootInfo"&amp;gt;&lt;br /&gt;  &amp;lt;h1 id="wootName"&amp;gt; {title} &amp;lt;/h1&amp;gt;&lt;br /&gt;   &amp;lt;div style="float:left; padding-right: 10px"&amp;gt;&lt;br /&gt;     &amp;lt;img src="{woot:thumbnailimage}" /&amp;gt;&lt;br /&gt;     &amp;lt;h3 id="wootPrice"&amp;gt;{woot:price} &amp;lt;/h3&amp;gt;&lt;br /&gt;     &amp;lt;h4&amp;gt;&amp;lt;a href="{woot:purchaseurl}" target="_blank"&amp;gt;Buy This Woot&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&lt;br /&gt;     &amp;lt;h3 id="wootPercent"&amp;gt;{woot:soldoutpercentage}% Sold Thus Far&amp;lt;/h3&amp;gt;&lt;br /&gt;   &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;div id="description" &amp;gt;{description}&amp;lt;/div&amp;gt;&lt;br /&gt; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here's the CSS:&lt;br /&gt;&lt;pre name="code" class="css"&gt;&lt;br /&gt;body {&lt;br /&gt; background:#EDEDED none repeat scroll 0 0;&lt;br /&gt; color:#191919;&lt;br /&gt; margin:0;&lt;br /&gt; padding:0;&lt;br /&gt;}&lt;br /&gt;h1 { font-size: 182%; margin-bottom: 0.5em}&lt;br /&gt;h3 {font-size:138.5%; margin-bottom: 0.5em}&lt;br /&gt;h4 {font-size:123.1%; margin-bottom: 0.5em}&lt;br /&gt;li {list-style-type:disc; list-style-position:inside}&lt;br /&gt;strong {font-weight:bold}&lt;br /&gt;p {margin-top: 1em}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This application can be run inside Tomcat or wherever you have a proxy running.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-7707897604137869260?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rQ_7TH8mJQbE9kFZhyZhU_VetuQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rQ_7TH8mJQbE9kFZhyZhU_VetuQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rQ_7TH8mJQbE9kFZhyZhU_VetuQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rQ_7TH8mJQbE9kFZhyZhU_VetuQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Abfkcopv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=wwIoqmxq"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=jMGTYCWi"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=jMGTYCWi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=UtjWRokl"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=UtjWRokl" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=uaME6r4C"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=uaME6r4C" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/zGlKDrCBviI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/7707897604137869260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=7707897604137869260" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7707897604137869260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/7707897604137869260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/zGlKDrCBviI/spry-woot-off-tracker.html" title="A Spry Woot-Off Tracker" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/12/spry-woot-off-tracker.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04BQn0yfCp7ImA9WxRUFU4.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-942019086080662665</id><published>2008-11-24T08:21:00.003-05:00</published><updated>2008-11-24T09:12:33.394-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-24T09:12:33.394-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Analytics" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>More Google Analytics in SAP Portal with jQuery</title><content type="html">One of the challenges with &lt;a href="http://twofourone.blogspot.com/2008/07/enhanced-google-analytics-in-sap-portal.html"&gt;SAP Portal and integrating Google Analytics&lt;/a&gt; is it's tendency to create a lot of links that pop content open in a new window.  Since you don't have access to the code that creates these URLs it causes a wee bit of a headache when you look to determine what items are being clicked on in the KM, or where your users are linking out of the portal to certain other applications.&lt;br /&gt;&lt;br /&gt;We can resolve some of this by using a javascript library to scrape the HTML page and insert some onclick events that will allow the items to be tracked.&lt;br /&gt;&lt;br /&gt;How can we accomplish this?&lt;br /&gt;&lt;br /&gt;There are two steps:&lt;br /&gt;&lt;br /&gt;First, add access to your favorite javascript library inside the Google Analytics code.   I've chosen &lt;a href="http://www.jquery.com"&gt;jQuery&lt;/a&gt;, although you could easily use other libraries.  You can do this through the ga-split-1.js file that was &lt;a href="http://twofourone.blogspot.com/2008/06/sap-portal-and-google-analytics.html"&gt;outlined earlier&lt;/a&gt;. Don't forget to change the name of the file if need be so it is not cached in users browsers.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="jscript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;document.write(unescape("%3Cscript src='http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By pulling jQuery from Google, we're increasing our load time, since we won't have to wait on connections to the Portal. The risk is low, since it's Google.  In addition, if jQuery isn't found, we just won't track certain types of links.  We'd still get the key pack clicking information.&lt;br /&gt;&lt;br /&gt;The second part is to actually use jQuery to track stuff.  You might be able to use the &lt;a href="http://plugins.jquery.com/project/gaTracker"&gt;jQuery GA &lt;/a&gt;plugin, but in my case, I decided to write my own javascript based upon the plugin to do the trick.  I would keep this code in a separate file and load it after you've initialized the pageTracker within your PortalComponent:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="jscript"&gt;&lt;br /&gt;function ga_decorateLink(u){&lt;br /&gt; var trackingURL = '';&lt;br /&gt; if(u.indexOf('://') == -1 &amp;amp;&amp;amp; u.indexOf('mailto:') != 0){&lt;br /&gt;  // no protocol or mailto - internal link - check extension&lt;br /&gt;  var ext = u.split('.')[u.split('.').length - 1];   &lt;br /&gt;  var exts = ['pdf','doc','xls','csv','jpg','gif', 'mp3','swf','txt','ppt','zip','gz','dmg','xml'] &lt;br /&gt;  for(i = 0; i &amp;lt; exts.length; i++){&lt;br /&gt;   if(ext == exts[i]){&lt;br /&gt;    // Likely grabbing an item from KM, etc.&lt;br /&gt;    trackingURL = '/downloads/' + u;&lt;br /&gt;    break;&lt;br /&gt;   }&lt;br /&gt;  }    &lt;br /&gt; } else {&lt;br /&gt;  if(u.indexOf('mailto:') == 0){&lt;br /&gt;   // mailto link - decorate&lt;br /&gt;   trackingURL = '/mailto/' + u.substring(7);     &lt;br /&gt;  } else {&lt;br /&gt;   // complete URL - check domain&lt;br /&gt;   var regex = /([^:\/]+)*(?::\/\/)*([^:\/]+)(:[0-9]+)*\/?/i;&lt;br /&gt;   var linkparts = regex.exec(u);&lt;br /&gt;   var urlparts = regex.exec(location.href);     &lt;br /&gt;   if(linkparts[2] != urlparts[2]) trackingURL = '/external/' + u; /*leaving the portal*/&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return trackingURL;   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Since you've initialized pageTracker in each Portal page, we're skipping that here.&lt;br /&gt;// just wait until the entire page loads&lt;br /&gt;$(document).ready(function(){&lt;br /&gt; $('a').each(function(){&lt;br /&gt;  var u = $(this).attr('href');&lt;br /&gt;   &lt;br /&gt;  if(typeof(u) != 'undefined'){&lt;br /&gt;   var newLink = decorateLink(u);&lt;br /&gt;   if(newLink.length){&lt;br /&gt;    $(this).click(function(){&lt;br /&gt;     $.pageTracker._trackPageview(newLink);&lt;br /&gt;    });&lt;br /&gt;   }&lt;br /&gt;  }    &lt;br /&gt; });&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you're using the defualt framework, be aware that you will not be able to track each and every link.  Javascript cannot dive into iframes on the page. Since it can't do that, you'll be unable to track each and every link, unless you can use embedded for that particular iView which will eliminate the iframes.&lt;br /&gt;&lt;br /&gt;Some fair warning here. This is from memory. I am no longer working with SAP Portal, so there is a good chance I've forgotten something here.  However, it did work on my last day working with Portal...at least the version at that gig. If you run into problems, please fix them and share them.  Don't hold onto it.  Share it with the rest of the SAP community, post it on your blog, or submit it to SDN for inclusion in their hosted materials. At the very least, post a solution in the SDN forums so that others can use this.  When you get it working, it's pretty darned cool!&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-942019086080662665?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xEtWyvrSnjH7K25_eyQzez3ToDo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xEtWyvrSnjH7K25_eyQzez3ToDo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xEtWyvrSnjH7K25_eyQzez3ToDo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xEtWyvrSnjH7K25_eyQzez3ToDo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=fz2PINIU"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=rVaTqdFM"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=ApFTQhC0"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=ApFTQhC0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=MehhUPBf"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=MehhUPBf" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=jXY5Xeil"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=jXY5Xeil" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/ySUTHC9zAxQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/942019086080662665/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=942019086080662665" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/942019086080662665?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/942019086080662665?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/ySUTHC9zAxQ/more-google-analytics-in-sap-portal.html" title="More Google Analytics in SAP Portal with jQuery" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/11/more-google-analytics-in-sap-portal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYDQ3c-fSp7ImA9WxRUEkU.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-2166067587013280617</id><published>2008-11-21T08:53:00.007-05:00</published><updated>2008-11-21T10:42:52.955-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T10:42:52.955-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Woot-Off" /><category scheme="http://www.blogger.com/atom/ns#" term="AIR" /><category scheme="http://www.blogger.com/atom/ns#" term="AIR Proxy" /><category scheme="http://www.blogger.com/atom/ns#" term="Woot" /><category scheme="http://www.blogger.com/atom/ns#" term="Flex" /><title>An AIR based Woot-Off tracker</title><content type="html">I've been going through some &lt;a href="http://www.adobe.com/products/flex/"&gt;Flex&lt;/a&gt; training this week.  It's an interesting tool, and pretty easy to make a quick application.  Unfortunately, the training has been a bit robotic in terms of being very prescriptive on how to perform somewhat elementary programming.  So it was time to take a break and actually try to attempt something that would be useful....or at least somewhat useful.&lt;br /&gt;&lt;br /&gt;Since we had a &lt;a href="http://www.woot.com/WhatIsWoot.aspx#q9"&gt;Woot-Off&lt;/a&gt; yesterday, I decided to use Flex to write a Woot-Off tracker.  A handy little &lt;a href="http://www.adobe.com/products/air/"&gt;AIR&lt;/a&gt; application to see when a new item appears.  It's a simple single windowed application that polls &lt;a href="http://www.woot.com/Blog/ViewEntry.aspx?Id=2118"&gt;Woot's API&lt;/a&gt; every 30 seconds, groks the RSSish feed, and displays information about the item being sold.&lt;br /&gt;&lt;br /&gt;In addition, it provides handy information regarding the status of the sale in terms of percentage of items sold and a button to purchase the product, or manually check Woot for an update.  If the percentage sold is above 94%, it ramps up the polling process to check Woot every second, since you never know when the &lt;a href="http://www.woot.com/Blog/ViewEntry.aspx?Id=1623"&gt;BOC&lt;/a&gt; will appear.&lt;br /&gt;&lt;br /&gt;The application is hardly complete.  It lacks any style or substance in terms of look and feel.  It also neglects the ability to run in the system tray (ala &lt;a href="http://www.twhirl.org/"&gt;Twhirl&lt;/a&gt; or &lt;a href="http://www.tweetdeck.com/"&gt;Tweetdeck&lt;/a&gt;) and update the user that an item might be selling out soon or that a new item is available.  Right now it simply runs on the screen.&lt;br /&gt;&lt;br /&gt;Of course, the trickiest part of this application is the need to run a Proxy service to hit an external URL.  Due to Flash's security model, and the lack of a &lt;a href="http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_14213"&gt;crossdomain.xml&lt;/a&gt; file at Woot, you need to have a local service running that will act as a proxy.  A quick Java servlet and the very very lightweight &lt;a href="http://winstone.sourceforge.net/"&gt;Winstone&lt;/a&gt; servlet container.  Ideally, you would launch this app with a little batch script that spun up your Servlet based proxy and then spun up the AIR app.&lt;br /&gt;&lt;br /&gt;So let's walk through the source.  That way, all of you out there who've actually done a lot of Flex and look at this and let me know what a BOC it is. :D  First we'll look at the AIR app, and finally the Java based Proxy.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="AS3"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"&lt;br /&gt;creationComplete="init()" width="500" height="370" xmlns:utils="flash.utils.*"&amp;gt;&lt;br /&gt;&amp;lt;mx:Script&amp;gt;&lt;br /&gt; &amp;lt;![CDATA[&lt;br /&gt;  import flash.net.navigateToURL;&lt;br /&gt;  import flash.utils.Timer;&lt;br /&gt;  import mx.formatters.Formatter;&lt;br /&gt;  import mx.formatters.NumberFormatter;&lt;br /&gt;  import mx.collections.ArrayCollection;&lt;br /&gt;  import mx.controls.Image;&lt;br /&gt;  import mx.rpc.events.ResultEvent;&lt;br /&gt;&lt;br /&gt;  private var START_QUICK_POLL_PERCENT:Number = 0.94;&lt;br /&gt;&lt;br /&gt;  // a 30 second and a 1 second Timer&lt;br /&gt;  private var wootPing:Timer = new Timer(30000, 1000000000);&lt;br /&gt;  private var wootEndPing:Timer = new Timer(1000, 1000000000);&lt;br /&gt;  private var checks:int = 0;&lt;br /&gt;&lt;br /&gt;  [Bindable] private var wootItemText:String = "No Woot Found...Yet";&lt;br /&gt;  [Bindable] private var wootItemPrice:String = "$10,000,000.00";&lt;br /&gt;  [Bindable] private var wootItemPercent:String = "0% Sold";&lt;br /&gt;  [Bindable] private var wootItemLink:String = "http://www.woot.com";&lt;br /&gt;  [Bindable] private var checkText:String= "Checked\n0 Times";&lt;br /&gt;  [Bindable] private var itemImgURL:String = "";&lt;br /&gt;&lt;br /&gt;  // Setup the Timers, and start the default timer &lt;br /&gt;  private function init():void {&lt;br /&gt;   wootPing.addEventListener(Event.ACTIVATE, wootHandler);&lt;br /&gt;   wootPing.addEventListener(TimerEvent.TIMER, wootHandler);&lt;br /&gt;   wootPing.start();&lt;br /&gt;   wootEndPing.addEventListener(TimerEvent.TIMER, wootHandler);&lt;br /&gt;  }  &lt;br /&gt; &lt;br /&gt;  // Handles the purchase button to open your browser&lt;br /&gt;  private function openWootWindow(event:MouseEvent):void {&lt;br /&gt;   var u:URLRequest = new URLRequest(wootItemLink);&lt;br /&gt;   flash.net.navigateToURL(u, "_blank");&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  // Generally use the Event to handle updating the app &lt;br /&gt;  private function wootHandler(event:Event):void {&lt;br /&gt;   getWoot();&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  // Hits the API.    &lt;br /&gt;  private function getWoot():void {&lt;br /&gt;   wootService.send();&lt;br /&gt;   checkCount.text = "Checked\n"+ ++checks + " times";&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  // Updates all of the items when the HTTPService completes&lt;br /&gt;  private function wootResultHandler(event:ResultEvent):void {&lt;br /&gt;   wootItemText = wootService.lastResult.rss.channel.item.title;&lt;br /&gt;   wootItemPrice = wootService.lastResult.rss.channel.item.price;&lt;br /&gt;   wootItemLink = wootService.lastResult.rss.channel.item.purchaseurl;&lt;br /&gt;   wootDesc.htmlText = wootService.lastResult.rss.channel.item.description;&lt;br /&gt;   wootImage.source =  wootService.lastResult.rss.channel.item.thumbnailimage;&lt;br /&gt;   // Determine if we need to do percentage checking.&lt;br /&gt;   if (!(new Boolean(wootService.lastResult.rss.channel.item.wootoff))) {&lt;br /&gt;    wootItemPercent = "This is not a Woot-Off";&lt;br /&gt;   } else {&lt;br /&gt;    var percentNum:Number = new Number(wootService.lastResult.rss.channel.item.soldoutpercentage);&lt;br /&gt;    wootItemPercent = new String(percentNum/100 + "% Sold");&lt;br /&gt;    // Do we need to start checking more often?&lt;br /&gt;    if (!wootEndPing.running &amp;amp;&amp;amp; percentNum &amp;gt; START_QUICK_POLL_PERCENT) {&lt;br /&gt;     wootEndPing.start();&lt;br /&gt;    } else if (wootEndPing.running &amp;amp;&amp;amp; percentNum &amp;lt; START_QUICK_POLL_PERCENT) {&lt;br /&gt;     wootEndPing.stop();&lt;br /&gt;    }&lt;br /&gt;   } &lt;br /&gt;  }&lt;br /&gt; ]]&amp;gt;&lt;br /&gt;&amp;lt;/mx:Script&amp;gt;&lt;br /&gt;&amp;lt;mx:HTTPService url="http://localhost:8080/WootProxy"&lt;br /&gt; id="wootService" result="wootResultHandler(event)" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:VBox left="5" right="5" top="5" bottom="5"&amp;gt;&lt;br /&gt; &amp;lt;mx:Label id="itemText" text="{wootItemText}" fontSize="12" fontWeight="bold"/&amp;gt;&lt;br /&gt; &amp;lt;mx:Canvas width="100%"&amp;gt;&lt;br /&gt;  &amp;lt;mx:Button toolTip="Click to purchase" label="Purchase" click="openWootWindow(event)" y="152" x="0"/&amp;gt;&lt;br /&gt;  &amp;lt;mx:TextArea height="300" id="wootDesc" left="150" right="0" /&amp;gt;&lt;br /&gt;  &amp;lt;mx:Image id="wootImage" width="142" height="116" left="0" top="0" &amp;gt;&lt;br /&gt;   &amp;lt;mx:source&amp;gt;http://upload.wikimedia.org/wikipedia/en/1/16/Wootlogo.png&amp;lt;/mx:source&amp;gt;&lt;br /&gt;  &amp;lt;/mx:Image&amp;gt;&lt;br /&gt;  &amp;lt;mx:Label id="checkCount" text="{checkText}" x="0" y="212" height="52" width="142"/&amp;gt;&lt;br /&gt;  &amp;lt;mx:Button toolTip="Click to load Woot" label="Check" click="getWoot()" y="182" /&amp;gt;&lt;br /&gt;  &amp;lt;mx:Label id="itemPrice" text="{wootItemPrice}" y="124" fontStyle="italic" fontSize="12" x="0"  width="142"/&amp;gt;&lt;br /&gt;  &amp;lt;mx:Label id="itemPercent" text="{wootItemPercent}" y="272" x="0"  width="142"/&amp;gt;&lt;br /&gt; &amp;lt;/mx:Canvas&amp;gt;&lt;br /&gt;&amp;lt;/mx:VBox&amp;gt;&lt;br /&gt;&amp;lt;/mx:WindowedApplication&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally the Proxy:&lt;br /&gt;&lt;pre name="code" class="Java"&gt;&lt;br /&gt;/*&lt;br /&gt;* To change this template, choose Tools | Templates&lt;br /&gt;* and open the template in the editor.&lt;br /&gt;*/&lt;br /&gt;package org.woot.tracker;&lt;br /&gt;&lt;br /&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.DataInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStreamReader;&lt;br /&gt;import java.io.OutputStream;&lt;br /&gt;import java.io.PrintWriter;&lt;br /&gt;import java.net.HttpURLConnection;&lt;br /&gt;import java.net.MalformedURLException;&lt;br /&gt;import java.net.URL;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;import javax.servlet.http.HttpServlet;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;import javax.servlet.http.HttpServletResponse;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author student&lt;br /&gt;*/&lt;br /&gt;public class WootProxy extends HttpServlet {&lt;br /&gt;&lt;br /&gt;static final long serialVersionUID = 1L;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Processes requests for both HTTP &amp;lt;code&amp;gt;GET&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;POST&amp;lt;/code&amp;gt; methods.&lt;br /&gt; * @param request servlet request&lt;br /&gt; * @param response servlet response&lt;br /&gt; * @throws ServletException if a servlet-specific error occurs&lt;br /&gt; * @throws IOException if an I/O error occurs&lt;br /&gt; */&lt;br /&gt;protected void processRequest(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;    throws ServletException, IOException {&lt;br /&gt;&lt;br /&gt;  String contentObj = "http://www.woot.com/salerss.aspx";&lt;br /&gt;&lt;br /&gt;  URL content = null;&lt;br /&gt;&lt;br /&gt;  if (null == contentObj) {&lt;br /&gt;    throw new ServletException("The destination url must be specified for ProxyHttpService");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;    content = new URL(contentObj);&lt;br /&gt;  } catch (MalformedURLException e) {&lt;br /&gt;    throw new ServletException(contentObj + " is a malformed url.");&lt;br /&gt;  }&lt;br /&gt;  HttpURLConnection contentCon = null;&lt;br /&gt;  try {&lt;br /&gt;    contentCon = (HttpURLConnection) content.openConnection();&lt;br /&gt;  } catch (IOException exception) {&lt;br /&gt;    throw new ServletException("Problem opening " + contentObj + ": " + exception.toString());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Get the content type from the URLConnection and set it on the response.&lt;br /&gt;  String contentType = contentCon.getContentType();&lt;br /&gt;  response.setContentType(contentType);&lt;br /&gt;&lt;br /&gt;  // Get and read the input stream.&lt;br /&gt;  StringBuffer buffer = new StringBuffer();&lt;br /&gt;&lt;br /&gt;  BufferedReader din =&lt;br /&gt;      new BufferedReader(new InputStreamReader(contentCon.getInputStream()));&lt;br /&gt;&lt;br /&gt;  String s;&lt;br /&gt;  while ((s = din.readLine()) != null) {&lt;br /&gt;    buffer.append(s);&lt;br /&gt;  }&lt;br /&gt;  din.close();&lt;br /&gt;&lt;br /&gt;  // Now write the bytes out to the client.&lt;br /&gt;  byte[] contentBytes = buffer.toString().getBytes();&lt;br /&gt;  OutputStream out = response.getOutputStream();&lt;br /&gt;  out.write(contentBytes, 0, contentBytes.length);&lt;br /&gt;  out.flush();&lt;br /&gt;  out.close();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// &amp;lt;editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."&amp;gt;&lt;br /&gt;/**&lt;br /&gt; * Handles the HTTP &amp;lt;code&amp;gt;GET&amp;lt;/code&amp;gt; method.&lt;br /&gt; * @param request servlet request&lt;br /&gt; * @param response servlet response&lt;br /&gt; * @throws ServletException if a servlet-specific error occurs&lt;br /&gt; * @throws IOException if an I/O error occurs&lt;br /&gt; */&lt;br /&gt;@Override&lt;br /&gt;protected void doGet(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;    throws ServletException, IOException {&lt;br /&gt;  processRequest(request, response);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Handles the HTTP &amp;lt;code&amp;gt;POST&amp;lt;/code&amp;gt; method.&lt;br /&gt; * @param request servlet request&lt;br /&gt; * @param response servlet response&lt;br /&gt; * @throws ServletException if a servlet-specific error occurs&lt;br /&gt; * @throws IOException if an I/O error occurs&lt;br /&gt; */&lt;br /&gt;@Override&lt;br /&gt;protected void doPost(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;    throws ServletException, IOException {&lt;br /&gt;  processRequest(request, response);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Returns a short description of the servlet.&lt;br /&gt; * @return a String containing servlet description&lt;br /&gt; */&lt;br /&gt;@Override&lt;br /&gt;public String getServletInfo() {&lt;br /&gt;  return "Short description";&lt;br /&gt;}// &amp;lt;/editor-fold&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;There it is, enjoy :)&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-2166067587013280617?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FXMJNwTknKHts9r4roDQy6s5eZE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FXMJNwTknKHts9r4roDQy6s5eZE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FXMJNwTknKHts9r4roDQy6s5eZE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FXMJNwTknKHts9r4roDQy6s5eZE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=ZmvjeMFR"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=WnAMlNYv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=HqxI0WxH"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=HqxI0WxH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=kli7yCtd"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=kli7yCtd" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=eymIpM2m"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=eymIpM2m" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/RDv2MAvmFFM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/2166067587013280617/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=2166067587013280617" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2166067587013280617?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/2166067587013280617?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/RDv2MAvmFFM/air-based-woot-off-tracker.html" title="An AIR based Woot-Off tracker" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/11/air-based-woot-off-tracker.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAHQn0-fCp7ImA9WxRQGUg.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-45747871293083749</id><published>2008-10-13T22:50:00.002-04:00</published><updated>2008-10-13T22:52:13.354-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-13T22:52:13.354-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trophymanager" /><category scheme="http://www.blogger.com/atom/ns#" term="TrExMa" /><title>TrExMa for Firefox 0.6.2</title><content type="html">TrophyManager.com players.  TrExMa 0.6.2 is finally available.  It should resolve most of the issues in getting a TrExMa rating since the update of TM's web site.&lt;br /&gt;&lt;br /&gt;http://code.google.com/p/trexma-for-firefox/&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-45747871293083749?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wbiJ5jysfqC50s71xCQZNNML8Dk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wbiJ5jysfqC50s71xCQZNNML8Dk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wbiJ5jysfqC50s71xCQZNNML8Dk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wbiJ5jysfqC50s71xCQZNNML8Dk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=h8slqKZr"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=mVoY3sGF"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=mhqSVEBk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=mhqSVEBk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=6jAhRIBE"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=6jAhRIBE" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=QXWjLA91"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=QXWjLA91" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/tCxnwSojqJY" height="1" width="1"/&gt;</content><link rel="related" href="http://code.google.com/p/trexma-for-firefox/" title="TrExMa for Firefox 0.6.2" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/45747871293083749/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=45747871293083749" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/45747871293083749?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/45747871293083749?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/tCxnwSojqJY/trexma-for-firefox-062.html" title="TrExMa for Firefox 0.6.2" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/10/trexma-for-firefox-062.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIFRngzcCp7ImA9WxRUEkU.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-3882534481970686140</id><published>2008-10-08T13:31:00.004-04:00</published><updated>2008-11-21T10:48:37.688-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T10:48:37.688-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="SAP" /><category scheme="http://www.blogger.com/atom/ns#" term="CSS" /><title>SAP Portal Javascript/CSS Service Enhanced</title><content type="html">The &lt;a href="http://twofourone.blogspot.com/2008/10/hacking-sap-portal-with-javascriptcss.html"&gt;service&lt;/a&gt; was enhanced today.&lt;br /&gt;&lt;br /&gt;What I discovered whilst doing more testing is that the service inserted the content very early in the lifecycle of the Portal.&lt;br /&gt;&lt;br /&gt;So lets say you inserted your CSS which fixes a bunch of SAPisms you can't fix using the theme editor.  Using the service you'd get output that looked like this:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt; &amp;lt;link href="/irj/portalapps/com.sap.portal.design.portaldesigndata/themes/portal/tillerTheme/glbl/glbl_nn7.css?7.0.15.0.25" rel="stylesheet"/&amp;gt;&lt;br /&gt; &amp;lt;link href="/irj/portalapps/com.sap.portal.design.portaldesigndata/themes/portal/tillerTheme/prtl_std/prtl_std_nn7.css?7.0.15.0.25" rel="stylesheet"/&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- EPCF: BOB Core --&amp;gt;&lt;br /&gt; &amp;lt;meta content="text/javascript" http-equiv="Content-Script-Type"/&amp;gt;&lt;br /&gt; &amp;lt;script src="/irj/portalapps/com.sap.portal.epcf.loader/script/optimize/js13_epcf.js?7.00001502"/&amp;gt;&lt;br /&gt; &amp;lt;script&amp;gt;&lt;br /&gt;  &amp;lt;!--&lt;br /&gt;// Snipped 30 lines of script&lt;br /&gt; &amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;!-- EPCF: EOB Core --&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!-- HTML Business for Java, 645_VAL_REL, 477869, Tue Feb 26 13:23:36 EST 2008 --&amp;gt;&lt;br /&gt; &amp;lt;!-- HTMLB: begin VARS --&amp;gt;&lt;br /&gt; &amp;lt;script language="JavaScript"&amp;gt;&lt;br /&gt;ur_system = {doc : window.document , mimepath :"/irj/portalapps/com.sap.portal.design.urdesigndata/themes/portal/tillerTheme/common/", stylepath : "/irj/portalapps/com.sap.portal.design.urdesigndata/themes/portal/tillerTheme/ur/", emptyhoverurl : "/irj/portalapps/com.sap.portal.htmlb/jslib/emptyhover.html", is508 : false, dateformat : 1, domainrelaxing : "MINIMAL"};&lt;br /&gt; &amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;!-- HTMLB: end   VARS --&amp;gt;&lt;br /&gt; &amp;lt;link type="text/css" href="http://your/css.css" rel="stylesheet"/&amp;gt;&lt;br /&gt;a bunch of scripts&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Oops, you're not after the theme at all.  You'd have to use !important all over the place.  How does one resolve this?&lt;br /&gt;&lt;br /&gt;You enhance the service.  In this case I used an example found by decompiling the LAFService, which is the actual theme service.  It provided examples on how to implement and use new IResource and IResourceInformation objects.  Here's the ExternalResource IResource object:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import com.sapportals.portal.prt.resource.IResource;&lt;br /&gt;import com.sapportals.portal.prt.resource.IResourceInformation;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Describes a resource which resides outside of the Portal landscape&lt;br /&gt;* Such resources could be external Javascript toolkits or CSS pages&lt;br /&gt;*&lt;br /&gt;*/&lt;br /&gt;public class ExternalResource implements IResource, Serializable {&lt;br /&gt;private IResourceInformation mm_resInfo;&lt;br /&gt;&lt;br /&gt;public ExternalResource(){}&lt;br /&gt;&lt;br /&gt;public IResourceInformation getResourceInformation(){&lt;br /&gt; return mm_resInfo;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void init(IResourceInformation resourceInformation) {&lt;br /&gt; mm_resInfo = resourceInformation;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public boolean isAvailable() {&lt;br /&gt; return mm_resInfo != null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Doesn't do much does it.  All of the work is in the init method and using the ExternalResourceInformation object which is an IResourceInformation:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import com.sapportals.portal.prt.component.IPortalComponentRequest;&lt;br /&gt;import com.sapportals.portal.prt.resource.IResourceInformation;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* Describes the ResourceInformation required by a resource that lives&lt;br /&gt;* outside of the Portal Landscape.&lt;br /&gt;*/&lt;br /&gt;public class ExternalResourceInformation  implements IResourceInformation, Serializable {&lt;br /&gt;&lt;br /&gt;private String mm_type;&lt;br /&gt;private String mm_fileName;&lt;br /&gt;private boolean mm_useFileName;&lt;br /&gt;private String mm_URL;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* @param resourceType - you should be using the static types defined in IResource.&lt;br /&gt;* @param URL - The URL to the resource you're trying to add&lt;br /&gt;*/&lt;br /&gt;public ExternalResourceInformation(String resourceType, String URL){&lt;br /&gt; mm_type = resourceType;&lt;br /&gt; mm_URL = URL;&lt;br /&gt;}&lt;br /&gt;/* (non-Javadoc)&lt;br /&gt;* @see com.sapportals.portal.prt.resource.IResourceInformation#getComponent()&lt;br /&gt;*/&lt;br /&gt;public String getComponent() {&lt;br /&gt; return "theNameOfYourService";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* (non-Javadoc)&lt;br /&gt;* @see com.sapportals.portal.prt.resource.IResourceInformation#getType()&lt;br /&gt;*/&lt;br /&gt;public String getType() {&lt;br /&gt; return mm_type;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* (non-Javadoc)&lt;br /&gt;* @see com.sapportals.portal.prt.resource.IResourceInformation#getSource()&lt;br /&gt;*/&lt;br /&gt;public String getSource() {&lt;br /&gt; return "";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* (non-Javadoc)&lt;br /&gt;* @see com.sapportals.portal.prt.resource.IResourceInformation#getURL(com.sapportals.portal.prt.component.IPortalComponentRequest)&lt;br /&gt;*/&lt;br /&gt;public String getURL(IPortalComponentRequest arg0) {&lt;br /&gt; return getURL();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getURL() {&lt;br /&gt; return mm_URL;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All of the work here is done in the constructor.  You just provide the URL and it will pass that to the IResource which will be included in the PortalResponse.&lt;br /&gt;&lt;br /&gt;What's amazing about this is how easy this actually was.  What's more amazing is how you need to decompile things to really understand how this works.  Most IResources are BaseResource objects.  Those objects are more complex since they need to ask the portal to build a URL to the resource you're attempting to include.  Therefore, using this method must be faster and lighter on the portal itself as well as the browser.&lt;br /&gt;&lt;br /&gt;One more thing to do.  Enhance the service objects:&lt;br /&gt;&lt;br /&gt;A new method signature in our interface:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public IResource getExternalCssResource(String cssURL);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;New methods in our implementation:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public IResource getExternalCssResource(String cssURL) {&lt;br /&gt; IResource ret = null;&lt;br /&gt; ret = getResource(IResource.CSS, cssURL);&lt;br /&gt; return ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private IResource getResource(String URL) {&lt;br /&gt;  IResource er = new ExternalResource();&lt;br /&gt;  IResourceInformation ri = new ExternalResourceInformation(resourceType, URL);&lt;br /&gt;  er.init(ri);&lt;br /&gt;  return er;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it.&lt;br /&gt;&lt;br /&gt;Now, if you create a simple "footer" portal component which does nothing but insert your IResource, you can have your CSS at the bottom of your page.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;IPortalComponentResponse componentResponse = (IPortalComponentResponse)pageContext.getAttribute(javax.servlet.jsp.PageContext.RESPONSE);&lt;br /&gt;IHtmlHeadService htmlHeadService =&lt;br /&gt; (IHtmlHeadService) PortalRuntime.getRuntimeResources().getService("com.scotts.tiller.portal.layouts.htmlheadservice.HtmlHeadService");&lt;br /&gt;IResource res = htmlHeadService.getExternalScriptResource("http://your/css.css");&lt;br /&gt;componentResponse.include(componentRequest, res);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now your stylesheet will appear after your portal theme.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-3882534481970686140?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/642rM-kBeRitXE3jHU_bkebwQNQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/642rM-kBeRitXE3jHU_bkebwQNQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/642rM-kBeRitXE3jHU_bkebwQNQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/642rM-kBeRitXE3jHU_bkebwQNQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=AZ8UfAoT"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=XjZsnqUv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=pXXpA7Gz"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=pXXpA7Gz" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=6DhJxeqS"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=6DhJxeqS" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=WALAJbof"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=WALAJbof" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/sX0Zny8gnhE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/3882534481970686140/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=3882534481970686140" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3882534481970686140?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3882534481970686140?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/sX0Zny8gnhE/sap-portal-javascriptcss-service.html" title="SAP Portal Javascript/CSS Service Enhanced" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/10/sap-portal-javascriptcss-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQDSH44cCp7ImA9WxRUEkU.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-173287070754717233</id><published>2008-10-06T14:21:00.005-04:00</published><updated>2008-11-21T10:46:19.038-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T10:46:19.038-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="SAP" /><category scheme="http://www.blogger.com/atom/ns#" term="CSS" /><title>Hacking SAP Portal with a Javascript/CSS Service</title><content type="html">One of the more, erm, "interesting features" of SAP Portal is the lack of ability to directly access the HTML HEAD tag and insert SCRIPT and LINK tags to your own CSS and Javascripts.  Well it's not impossible to do, but SAP doesn't offer this out of the box straight away.  Probably because they don't want you breaking things.&lt;br /&gt;&lt;br /&gt;But lets say you want to use the Dojo Toolkit or YUI on a new hip AbstractPortalComponent.  But you don't want to download and host the scripts locally.  You wish to use AOLs CDN or Yahoo's CDN to load the javascript.  It's faster and solid in terms of reliability. How can you accomplish this?&lt;br /&gt;&lt;br /&gt;The answer is, you need to write a new service to access the HTML HEAD.&lt;br /&gt;&lt;br /&gt;Create a service inside NWDS and call it, HtmlHeadService.  NWDS will create an interface for the service and an implementation.  Go to IHtmlHeadService and insert the following method signatures:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.portal.htmlheadservice;&lt;br /&gt;&lt;br /&gt;import com.sapportals.portal.prt.service.IService;&lt;br /&gt;import com.sapportals.portal.prt.component.IPortalComponentRequest;&lt;br /&gt;&lt;br /&gt;public interface IHtmlHeadService extends IService {&lt;br /&gt;&lt;br /&gt;  public static final String KEY = "HtmlHeadService";&lt;br /&gt;&lt;br /&gt;  public void addScript(IPortalComponentRequest request, String scriptURL, String type);&lt;br /&gt;  public void addJS(IPortalComponentRequest request, String jsURL);&lt;br /&gt;  public void addLink(IPortalComponentRequest request, String linkURL, String type, String rel);&lt;br /&gt;  public void addCSSLink(IPortalComponentRequest request, String linkURL);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is pretty simple so far.   Next look at the HtmlHeadService object:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.portal.htmlheadservice;&lt;br /&gt;&lt;br /&gt;import com.sapportals.portal.prt.service.IServiceContext;&lt;br /&gt;import com.sapportals.portal.prt.logger.ILogger;&lt;br /&gt;import com.sapportals.portal.prt.runtime.IPortalConstants;&lt;br /&gt;import com.sapportals.portal.prt.component.IPortalComponentRequest;&lt;br /&gt;import com.sapportals.portal.prt.pom.IPortalNode;&lt;br /&gt;import com.sapportals.portal.prt.connection.PortalHtmlResponse;&lt;br /&gt;import com.sapportals.portal.prt.connection.IPortalResponse;&lt;br /&gt;import com.sapportals.portal.prt.util.html.HtmlDocument;&lt;br /&gt;import com.sapportals.portal.prt.util.html.HtmlHead;&lt;br /&gt;import com.sapportals.portal.prt.util.html.HtmlScript;&lt;br /&gt;import com.sapportals.portal.prt.util.html.HtmlLink;&lt;br /&gt;&lt;br /&gt;public class HtmlHeadService implements IHtmlHeadService{&lt;br /&gt;&lt;br /&gt;  private IServiceContext mm_serviceContext;&lt;br /&gt;  private ILogger         mm_logger;&lt;br /&gt;&lt;br /&gt;  public void init(IServiceContext serviceContext) {&lt;br /&gt;      mm_serviceContext = serviceContext;&lt;br /&gt;      mm_logger = serviceContext.getLogger(IPortalConstants.SERVICE_LOGGER);&lt;br /&gt;      mm_logger.info(this, "Initialization of HtmlHeadAccessor");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void afterInit() {&lt;br /&gt;      mm_logger.info(this, "After Initialization of HtmlHeadAccessor");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void configure(com.sapportals.portal.prt.service.IServiceConfiguration configuration) {}&lt;br /&gt;&lt;br /&gt;  public void destroy() {}&lt;br /&gt;&lt;br /&gt;  public void release()  {}&lt;br /&gt;&lt;br /&gt;  public IServiceContext getContext() {&lt;br /&gt;      return mm_serviceContext;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String getKey() {&lt;br /&gt;      return KEY;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void addLink(IPortalComponentRequest request, String linkURL, String type, String rel) {&lt;br /&gt;      HtmlHead docHead = getHtmlHead(request);&lt;br /&gt;      if (docHead != null) {&lt;br /&gt;          HtmlLink link = new HtmlLink(linkURL);&lt;br /&gt;          link.setType(type);&lt;br /&gt;          link.setRel(rel);&lt;br /&gt;          docHead.addElement(link);&lt;br /&gt;      } else {&lt;br /&gt;          mm_logger.severe("Could not get HtmlHead from PortalResponse");&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void addCSSLink(IPortalComponentRequest request, String linkURL) {&lt;br /&gt;      addLink(request, linkURL, "text/css", "stylesheet");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void addScript(IPortalComponentRequest request, String scriptURL, String type) {&lt;br /&gt;      HtmlHead docHead = getHtmlHead(request);&lt;br /&gt;      if (docHead != null) {&lt;br /&gt;          HtmlScript script = new HtmlScript();&lt;br /&gt;          script.setSrc(scriptURL);&lt;br /&gt;          script.setType(type);&lt;br /&gt;          docHead.addElement(script);&lt;br /&gt;      } else {&lt;br /&gt;          mm_logger.severe("Could not get HtmlHead from PortalResponse");&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void addJS(IPortalComponentRequest request, String jsURL) {&lt;br /&gt;      addScript(request, jsURL, "text/javascript");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /* This contains the deprecated method getHtmlDocument().  If this fails, check&lt;br /&gt;   * the Web Page Composer based service cssService.  It uses the exact same&lt;br /&gt;   * method.  If this is failing, it should be failing.&lt;br /&gt;   */&lt;br /&gt;  private HtmlHead getHtmlHead(IPortalComponentRequest request) {&lt;br /&gt;      HtmlHead docHead = null;&lt;br /&gt;      IPortalNode node = request.getNode().getPortalNode();&lt;br /&gt;      IPortalResponse resp = (IPortalResponse) node.getValue(IPortalResponse.class.getName());&lt;br /&gt;      try {&lt;br /&gt;          PortalHtmlResponse htmlResp = (PortalHtmlResponse) resp;&lt;br /&gt;          HtmlDocument doc = htmlResp.getHtmlDocument();&lt;br /&gt;          docHead = doc.getHead();&lt;br /&gt;      } catch (Exception cce) {&lt;br /&gt;          mm_logger.severe("Exception found: " + cce.getMessage());&lt;br /&gt;          cce.printStackTrace(System.err);&lt;br /&gt;      }&lt;br /&gt;      return docHead;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's the meat of the matter.  What does this code do?  It uses some undocumented objects to gain access to an HtmlDocument object.  This object gives you full access to the entire web page.  In this case we're just grabbing a head, you could do much more if you so choose.&lt;br /&gt;&lt;br /&gt;So what about the deprecated method getHtmlDocument(), seems bad.  Well, with the exception of the fact that SAP is using the exact same method in the recently released Web Page Composer tool, I wouldn't be worried.  WPC uses this method to grab its style sheets and javascripts from the KM repositiory.  The cool thing is, the code can be repurposed to place anything you like into the page.&lt;br /&gt;&lt;br /&gt;How to finalize the service?  It needs a ton of SharingReferences in the portalapp.xml file to make it go.  This is probably more than it needs, but cssService was using this exact string:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;"connection,usermanagement, knowledgemanagement, landscape, htmlb, exportalJCOclient, exportal"&lt;/pre&gt;&lt;br /&gt;With this service you can easily create a PortalComponent that accesses external stylesheets and javascripts to give your portal that custom look and feel that it's been lacking.  Some folks have used this method to change the Portal Title and other features as well.  Thanks to &lt;a href="https://www.sdn.sap.com/irj/sdn/profile?userID=965&amp;amp;start=0"&gt;Darrell Merryweather&lt;/a&gt; at SAP for the inspiration.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-173287070754717233?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-0Df5VTv6zC9Ok0z45PUzrZVc04/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-0Df5VTv6zC9Ok0z45PUzrZVc04/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-0Df5VTv6zC9Ok0z45PUzrZVc04/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-0Df5VTv6zC9Ok0z45PUzrZVc04/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=iph4OWVl"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=VKhtpexU"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=NJnsvQqY"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=NJnsvQqY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=z5I8FKeV"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=z5I8FKeV" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=FoZUGqUQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=FoZUGqUQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/OubGFNJhnAc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/173287070754717233/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=173287070754717233" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/173287070754717233?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/173287070754717233?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/OubGFNJhnAc/hacking-sap-portal-with-javascriptcss.html" title="Hacking SAP Portal with a Javascript/CSS Service" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/10/hacking-sap-portal-with-javascriptcss.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIMQ306eCp7ImA9WxRUEkU.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-3135447400361269321</id><published>2008-08-29T08:51:00.003-04:00</published><updated>2008-11-21T10:49:42.310-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T10:49:42.310-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="KM" /><category scheme="http://www.blogger.com/atom/ns#" term="SAP" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>XSLT in SAP Portal's Knowledge Management</title><content type="html">One of the features of SAP's Portal application is a Knowledge Management library.  Think of it as a JSR-170 application that's not JSR-170 compliant.&lt;br /&gt;&lt;br /&gt;One of the challenges of working with this library is the lack of meaningful documentation.  It's difficult to parse exactly how it works by just looking at the &lt;a href="https://help.sap.com/javadocs/NW04S/current/km/index.html"&gt;javadocs&lt;/a&gt;. There are some examples of what you can do, but they require strange configurations and occasionally bouncing the Portal.  Considering a bounce can take 20-30 minutes rather than seconds, that's not an ideal situation.&lt;br /&gt;&lt;br /&gt;Let's examine an idea that the UI/Usability designer has had on my current project.  He wanted to simply drop XML into the Portal and use XSLT to give the look and feel he was looking for on individual pages.&lt;br /&gt;&lt;br /&gt;Seems like a reasonable request.  After much searching, I found this &lt;a href="https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/com.sap.km.cm.docs/library/netweaver/netweaver-developers-guide-2004s/NetWeaverDevelopersGuide2004s_Documents/KM_articles_new/howto/rf/global_service_api/how_to_pipeline.html"&gt;document&lt;/a&gt; on how to do that within SAP's KM. Go ahead, give it a read. Seems straight forward except for the bouncing of the server and the fact that it is focused more on XML documents rather than XML for the sake of having HTML look proper within the portal. If you've spend any time with Firebug looking at Portal output, you'll understand where I'm coming from.&lt;br /&gt;&lt;br /&gt;Needless to say, this seemed highly difficult to actually implement.  I don't want to have to bounce a server for each page we develop or each mistake we might make with the XSLT.  Velocity of development would be far too slow.&lt;br /&gt;&lt;br /&gt;Therefore I set off on a journey to figure out just how the KM APIs work.  I ended up with the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import com.sapportals.portal.prt.component.*;&lt;br /&gt;import com.sapportals.wcm.repository.*;&lt;br /&gt;import com.sapportals.wcm.util.uri.*;&lt;br /&gt;import com.sapportals.wcm.util.usermanagement.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import org.jdom.*;&lt;br /&gt;import org.jdom.input.*;&lt;br /&gt;import org.jdom.output.*;&lt;br /&gt;import org.jdom.transform.*;&lt;br /&gt;&lt;br /&gt;import javax.xml.transform.stream.*;&lt;br /&gt;import javax.xml.transform.*;&lt;br /&gt;&lt;br /&gt;public class KmXmlTransformer extends AbstractPortalComponent {&lt;br /&gt; &lt;br /&gt;  public void doContent(IPortalComponentRequest request, IPortalComponentResponse response) {&lt;br /&gt; IPortalComponentProfile profile = request.getComponentContext().getProfile();&lt;br /&gt; String xmlDocument = profile.getProperty("XmlDocumentPath");&lt;br /&gt; String xsltDocument = profile.getProperty("XsltDocumentPath");&lt;br /&gt;&lt;br /&gt; try {  &lt;br /&gt;  com.sap.security.api.IUser user=(com.sap.security.api.IUser)request.getUser();&lt;br /&gt;  com.sapportals.portal.security.usermanagement.IUser epUser = WPUMFactory.getUserFactory().getEP5User(user);&lt;br /&gt;  ResourceContext ctx= new ResourceContext(epUser);&lt;br /&gt;  &lt;br /&gt;  RID xmlRid=RID.getRID(xmlDocument);&lt;br /&gt;  IResource xmlResource = (ResourceFactory.getInstance().getResource(xmlRid, ctx));&lt;br /&gt;  &lt;br /&gt;  RID xslRid=RID.getRID(xsltDocument);&lt;br /&gt;  IResource xslResource = (ResourceFactory.getInstance().getResource(xslRid, ctx));&lt;br /&gt;  &lt;br /&gt;  SAXBuilder builder = new SAXBuilder();&lt;br /&gt;   &lt;br /&gt;  Document docXml = builder.build(xmlResource.getContent().getInputStream());&lt;br /&gt;  Document resultDoc = null;&lt;br /&gt;   &lt;br /&gt;  TransformerFactory transformerFactory = TransformerFactory.newInstance();&lt;br /&gt;  Templates stylesheet =&lt;br /&gt;    transformerFactory.newTemplates(new StreamSource(xslResource.getContent().getInputStream()));&lt;br /&gt;  Transformer xslTransformer = stylesheet.newTransformer();&lt;br /&gt;   &lt;br /&gt;  JDOMResult jdRes = new JDOMResult();&lt;br /&gt;  JDOMSource jdSrc = new JDOMSource(docXml);&lt;br /&gt;  xslTransformer.transform(jdSrc, jdRes);&lt;br /&gt;   &lt;br /&gt;  resultDoc = jdRes.getDocument();&lt;br /&gt;&lt;br /&gt;  XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());&lt;br /&gt;  outputter.output(resultDoc, response.getWriter());&lt;br /&gt;     &lt;br /&gt; } catch (Exception e) {&lt;br /&gt;    e.printStackTrace(System.err); &lt;br /&gt; }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;So what does this do?  It uses JDOM and an XSLT engine to take an XML file in the repository and transform it with an XSLT file in the repository.  It uses properties (XmlDocumentPath, XsltDocumentPath) to define where in the KM those files are.  These are configurable so that you can simply reuse this object and just modify the properties to choose different files.&lt;br /&gt;&lt;br /&gt;There are some issues with the code.  Obviously, it's limited to a single transform in its current form.  It also uses a deprecated API in the first three lines of the try block.  com.sapportals.portal.security.usermanagement.IUser is a deprecated class.  Unfortunately you can't create a ResourceContext without one.  Nice professionalism by SAP to not offer an alternative.&lt;br /&gt;&lt;br /&gt;Other than those limitations, it works pretty darn well.  The only question left to analyze is how well this scales.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-3135447400361269321?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jV1cBN6PXBpsFkYoXUMaK3CbOhM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jV1cBN6PXBpsFkYoXUMaK3CbOhM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jV1cBN6PXBpsFkYoXUMaK3CbOhM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jV1cBN6PXBpsFkYoXUMaK3CbOhM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=O9gIHoL6"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=MYhwSyHj"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=xZXVrfuP"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=xZXVrfuP" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=R93dDICA"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=R93dDICA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=XJjGYvdm"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=XJjGYvdm" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/LwLEdUX5IsU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/3135447400361269321/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=3135447400361269321" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3135447400361269321?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3135447400361269321?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/LwLEdUX5IsU/xslt-in-sap-portals-knowledge.html" title="XSLT in SAP Portal's Knowledge Management" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/08/xslt-in-sap-portals-knowledge.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4GSHs6fip7ImA9WxdUEU0.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-4447400513834307282</id><published>2008-07-26T09:21:00.002-04:00</published><updated>2008-07-26T15:35:29.516-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-26T15:35:29.516-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Analytics" /><title>Updating Javascript in SAP Portal</title><content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Quick reminder to those of you who've followed my &lt;a href="http://twofourone.blogspot.com/2008/07/enhanced-google-analytics-in-sap-portal.html"&gt;posts&lt;/a&gt; on Google Analytics.&lt;br /&gt;&lt;br /&gt;Be sure that if you're updating a Javascript file that you take the time to update the version of the file.  SAP Portal does this using a query string like construct after the javascript file for its OOTB components.&lt;br /&gt;&lt;br /&gt;You can do a similar construct for your files by simply embedding a version into the file name.  Following the previous GA example, you can simply update the file name to be ga-split-2.0.1.js&lt;br /&gt;&lt;br /&gt;Of course, the next step is to update the PortalComponent to pull in the correct version of the file.&lt;br /&gt;&lt;br /&gt;So why do you need to do this?  Depending upon how your Portal and Load Balancers are setup with caching and expires headers, you won't push the correct version of the javascript file to the browser unless you update the file name!  Why?  It's common practice to set Expires headers in the far future and set the browser to cache the javascript file.  If your setup is doing that, then any changes you make the the original JS file will not be pulled in unless your users happened to clear their browser cache.  Since the chance of your entire user community pulling that off is miniscule, the only way to force them to get the new version of the file is to update the file name!&lt;br /&gt;&lt;br /&gt;Also, be sure you head over and look at what Spyvee did to inspire these posts over at &lt;a href="http://www.netweavercentral.com/"&gt;NetweaverCentral&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-4447400513834307282?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xqIN49ojmLGktfW_NEXR9AEV7YY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xqIN49ojmLGktfW_NEXR9AEV7YY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xqIN49ojmLGktfW_NEXR9AEV7YY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xqIN49ojmLGktfW_NEXR9AEV7YY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=9pLYJDG8"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=nsQdd6Ox"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Gl7eZu6X"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=Gl7eZu6X" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=y4YoHLEA"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=y4YoHLEA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=XWQes0zc"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=XWQes0zc" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/_kLv56TgHRA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/4447400513834307282/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=4447400513834307282" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/4447400513834307282?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/4447400513834307282?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/_kLv56TgHRA/updating-javascript-in-sap-portal.html" title="Updating Javascript in SAP Portal" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/07/updating-javascript-in-sap-portal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQEQ3ozeSp7ImA9WxRUFU4.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-6544860966248118182</id><published>2008-07-17T09:30:00.004-04:00</published><updated>2008-11-24T08:11:42.481-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-24T08:11:42.481-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Analytics" /><category scheme="http://www.blogger.com/atom/ns#" term="SAP" /><title>Enhanced Google Analytics in SAP Portal</title><content type="html">If you happened to follow my &lt;a href="http://twofourone.blogspot.com/2008/06/sap-portal-and-google-analytics.html"&gt;post&lt;/a&gt; on integrating Google Analytics with SAP Portal, and attempted to implement it, you may have found some challenges with the reports.  More specifically:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If you're using the Light Framework (or derivation), all of your URLs are unreadable.  They don't describe what is going on in the page since the Portal uses GUIDs as a URL parameter to gather the appropriate page.&lt;/li&gt;&lt;li&gt;If you're using the Default Framework (or derivation), you only show hits on your entry point.  Which is great for gathering browser information, but not so much for following user activity.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In order to resolve this problem, you decide to add the Analytics iView to other pages in your Portal.  Now all of your URLs are &lt;i&gt;really&lt;/i&gt; unreadable.  In fact, you will find that you receive multiple URLs for the same page, where the only difference is the windowID in the query string.  This makes the data flat out unusable.&lt;/li&gt;&lt;/ul&gt;So, what to do?&lt;br /&gt;&lt;br /&gt;There is a single fix that resolves both issues. The fix involves asking Portal where in the Navigation Tree you are. First, add in some imports to your code:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="Java"&gt;import com.sapportals.portal.navigation.INavigationNode;&lt;br /&gt;import com.sapportals.portal.navigation.NavigationEventsHelperService;&lt;br /&gt;import com.sapportals.portal.prt.runtime.PortalRuntime;&lt;br /&gt;import com.sapportals.portal.prt.pom.IEvent;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to use these, you'll need to get the following JARs and import them into your project:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;com.sap.portal.navigation.api_service_api.jar&lt;/li&gt;&lt;li&gt;com.sap.portal.navigation.helperservice_api.jar&lt;/li&gt;&lt;li&gt;com.sap.portal.navigation.helperservice_core.jar&lt;/li&gt;&lt;/ul&gt;One of the methods you can override in an AbstractPortalComponent is doOnNodeReady().  This method is called once the PortalNode has been constructed.  At this point, the node can ask the Portal for information.  The method is implemented as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="JAVA"&gt;    &lt;br /&gt;protected void doOnNodeReady(IPortalComponentRequest request,IEvent arg1) {&lt;br /&gt;    // Get the service to access the Navigation information&lt;br /&gt;    NavigationEventsHelperService helperService =(NavigationEventsHelperService) PortalRuntime.getRuntimeResources().getService("com.sap.portal.navigation.helperservice.navigation_events_helper");&lt;br /&gt;    // Get your current location in the navigation tree&lt;br /&gt;    INavigationNode navTargetNode = helperService.getCurrentLaunchNavNode(request);&lt;br /&gt;    StringBuffer fullPath = new StringBuffer(navTargetNode.getTitle(Locale.ENGLISH));&lt;br /&gt;    // After stashing the title of the node, get the node's parent and loop&lt;br /&gt;    // until you've reached the top node.  Stash each parent's name and build&lt;br /&gt;    // a navigation "path" for use later.&lt;br /&gt;    INavigationNode aParent = helperService.getParentNode(navTargetNode, request);&lt;br /&gt;    while (aParent != null &amp;amp;&amp;amp; !aParent.getTitle(Locale.ENGLISH).equals("")) {&lt;br /&gt;        fullPath.insert(0, aParent.getTitle(Locale.ENGLISH) + "/");&lt;br /&gt;        aParent = helperService.getParentNode(aParent, request);&lt;br /&gt;    }&lt;br /&gt;    // store the path in a member variable that can be used inside doContent()&lt;br /&gt;    pageTitle = fullPath.toString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you've created this path, you can then use it to track the page properly.  Inside ga-split-2.js, you should remove the final line which calls pageTracker._trackPageview()  Instead, you'll create a set of response.write() calls to use the pageTitle object and write a new snippet of code on each specific page.&lt;br /&gt;&lt;br /&gt;The end of doContent will look as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="Java"&gt;&lt;br /&gt;response.include(request, googleAnalyticsDataResource2);&lt;br /&gt;response.write("&amp;lt;script type=\"text/javascript\"&amp;gt;\n");&lt;br /&gt;response.write("pageTracker._trackPageview(\""+ pageTitle +"\");\n");&lt;br /&gt;response.write("&amp;lt;/script&amp;gt;");&lt;br /&gt;&lt;br /&gt;response.setContentType(PortalComponentContentType.HTML);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;How to use the enhancements:&lt;br /&gt;&lt;br /&gt;If you're in the light framework, it will just work.  You can keep the code at the framework level and it will work on every page in the portal.  If you're in the default framework, you'll need to add the code to each page that you want to track.  You may want to remove the code from the framework and just track pages.  The resulting reports will be far more readable and much better for your business users and portal sponsors who would likely be consuming the data (and pretty graphs) that Google Analytics provides.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-6544860966248118182?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1uaJKdASSUVc_9QPf-cWL3y9puI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1uaJKdASSUVc_9QPf-cWL3y9puI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1uaJKdASSUVc_9QPf-cWL3y9puI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1uaJKdASSUVc_9QPf-cWL3y9puI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=iIgfHVcj"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=N4H63YFb"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=LogwgycF"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=LogwgycF" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=T2X7vgID"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=T2X7vgID" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Xu0PEwAY"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=Xu0PEwAY" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/11bwkgvAGPg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/6544860966248118182/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=6544860966248118182" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/6544860966248118182?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/6544860966248118182?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/11bwkgvAGPg/enhanced-google-analytics-in-sap-portal.html" title="Enhanced Google Analytics in SAP Portal" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/07/enhanced-google-analytics-in-sap-portal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08AQHk-fCp7ImA9WxdWEEw.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-3704025188967915681</id><published>2008-07-02T13:27:00.002-04:00</published><updated>2008-07-02T13:30:41.754-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-02T13:30:41.754-04:00</app:edited><title>How does a pacemaker get infected?</title><content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;A friend of mine from college has an ICD in his chest.  He's had it there for 20 years.  Basically if his heart gets messed up, it restarts it.  Knocks him on his ass and everything if it gets triggered.  It looks really funny, but apparently isn't if you're the one getting knocked down (Insert annoying TumbaWumba song here)&lt;br /&gt;&lt;br /&gt;Anyway, somehow, it got infected.  Now he's up at the Cleveland Clinic &lt;a href="http://www.cicora.com/index.php/2008/07/01/26th-post/"&gt;getting a new one&lt;/a&gt;.  Not quite certain how an internal item gets infected, but I guess it's possible, since it happened.  Love to hear how that actually happens.&lt;br /&gt;&lt;br /&gt;Been thinking about him quite a bit recently.  He's going through some pretty annoying stuff due to his condition.  Hopefully it goes well and without issue and he can get home and recover soon.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-3704025188967915681?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qmduT2HADbIs5paz4lJrIim-yUI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qmduT2HADbIs5paz4lJrIim-yUI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qmduT2HADbIs5paz4lJrIim-yUI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qmduT2HADbIs5paz4lJrIim-yUI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=6vKycrXM"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=dgLNUGNF"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=6CJxYy7P"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=6CJxYy7P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=UPNXwODZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=UPNXwODZ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=JK5o2SnW"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=JK5o2SnW" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/aSb50uImqr4" height="1" width="1"/&gt;</content><link rel="related" href="http://www.cicora.com/index.php/2008/07/01/26th-post/" title="How does a pacemaker get infected?" /><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/3704025188967915681/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=3704025188967915681" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3704025188967915681?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3704025188967915681?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/aSb50uImqr4/how-does-pacemaker-get-infected.html" title="How does a pacemaker get infected?" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/07/how-does-pacemaker-get-infected.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8DQX8yfip7ImA9WxRUFU4.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-1789817701309545734</id><published>2008-06-18T14:53:00.007-04:00</published><updated>2008-11-24T08:21:10.196-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-24T08:21:10.196-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SAP Portal" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Analytics" /><category scheme="http://www.blogger.com/atom/ns#" term="SAP" /><title>SAP Portal and Google Analytics</title><content type="html">Some folks over at Spyvee created a &lt;a href="https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/50b94044-7008-2b10-1680-c04e4526367b"&gt;document&lt;/a&gt; on how to integrate &lt;a href="http://www.google.com/analytics/"&gt;Google Analytics&lt;/a&gt; with &lt;a href="https://www.sdn.sap.com/irj/sdn/nw-portalandcollaboration"&gt;SAP Portal&lt;/a&gt;.  It's a very good document but, I didn't care for the fact that the code would not be entered in a standard place for javascript.&lt;br /&gt;&lt;br /&gt;Essentially SAP takes a lot of ownership over how objects are inserted into the portal.  Ideally you'd want to place the Google Anayltics code right above the tag in your page.  Portal doesn't quite let you do that.  At least not with any ease.&lt;br /&gt;&lt;br /&gt;The next best place for javascript code is at the bottom of the head....at least in SAP Portal.  Why?  Because you can easily place it there using an AbstractPortalComponent.&lt;br /&gt;&lt;br /&gt;Here's some modified steps to Spyvee's document that will allow you to insert Google Analytics into your Portal Framework and track a whole lot of clicks.&lt;br /&gt;&lt;br /&gt;Netweaver Portal Integration:&lt;br /&gt;&lt;br /&gt;When you get to this part, create a PAR with an AbstractPortalComponent.  Create something like this:&lt;br /&gt;&lt;pre name="code" class="Java"&gt;&lt;br /&gt;package com.corp.portal.tools;&lt;br /&gt;&lt;br /&gt;import com.sapportals.portal.prt.component.*;&lt;br /&gt;import com.sapportals.portal.prt.resource.IResource;&lt;br /&gt;&lt;br /&gt;public class GoogleAnalytics extends AbstractPortalComponent {&lt;br /&gt;&lt;br /&gt;  public void doContent(IPortalComponentRequest request, IPortalComponentResponse response) {&lt;br /&gt;    IResource googleAnalyticsDataResource = request.getResource(IResource.SCRIPT, "scripts/ga-split-1.js");&lt;br /&gt;    response.include(request, googleAnalyticsDataResource);&lt;br /&gt;    IResource googleAnalyticsDataResource2 = request.getResource(IResource.SCRIPT, "scripts/ga-split-2.js");&lt;br /&gt;    response.include(request, googleAnalyticsDataResource2);&lt;br /&gt; response.setContentType(PortalComponentContentType.HTML);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What this code will do is pull two scripts that you will create in the scripts directory of the portal application.  These two scripts will be the two parts of the ga.js code you grabbed from Google.  The code is split into two pieces surrounded by script tags.  So creating the following script files will do the trick:&lt;br /&gt;&lt;br /&gt;ga-split-1.js:&lt;br /&gt;&lt;pre name="code" class="jscript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;ga-split-2.js:&lt;br /&gt;&lt;pre name="code" class="jscript"&gt;var pageTracker = _gat._getTracker("UA-XXXXXX-3");&lt;br /&gt;pageTracker._initData();&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Obviously, don't copy this straight as you'll want your personalized tracking code instead of XXXXXXX :)&lt;br /&gt;&lt;br /&gt;Once you've uploaded and created an iView, stash the iView at the bottom of your framework.  I'm assuming you needed to customize it and aren't using the out of the box SAP framework.  If you stash the iView at the bottom, and it's working, you'll see two script tags  in the head to your two scripts, and you'll find a script between them calling the google-analytics.com/ga.js script. &lt;br /&gt;&lt;br /&gt;Eventually Google will pick up that it's working and you'll begin to track your clicks.  Just beware that if you're behind a firewall, you will probably get some strange results as to where your clicks are being routed depending upon your network topology.  I've got requests in Ohio showing up as Chicago, which is where the google analytics call is being routed.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-1789817701309545734?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D1RTRtoC-Y4N27VMeC8Nv8ytHhI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D1RTRtoC-Y4N27VMeC8Nv8ytHhI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D1RTRtoC-Y4N27VMeC8Nv8ytHhI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D1RTRtoC-Y4N27VMeC8Nv8ytHhI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=5gCz1QK4"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=gFedQujN"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=1GnpmcnD"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=1GnpmcnD" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=K5i4kj1E"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=K5i4kj1E" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=SybTHBXl"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=SybTHBXl" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/5oax2Gr2JjE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/1789817701309545734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=1789817701309545734" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1789817701309545734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/1789817701309545734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/5oax2Gr2JjE/sap-portal-and-google-analytics.html" title="SAP Portal and Google Analytics" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/06/sap-portal-and-google-analytics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYNQHg_fip7ImA9WxdSE0w.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-5528227923680029766</id><published>2008-05-20T15:35:00.002-04:00</published><updated>2008-05-20T15:36:31.646-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-20T15:36:31.646-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="crew" /><category scheme="http://www.blogger.com/atom/ns#" term="hilliard" /><title>Hilliard to gain Crew Facility</title><content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;div style=""&gt;According to the Dispatch, and Shawn Mitchell, Hilliard is getting the Crew Training ground.&lt;br /&gt;&lt;br /&gt;This is undoubtedly good news for the school district and the city.  But I still sit and stratch my head trying to figure out how the infrastructure will support the facility.  Can you imaging the travelling hordes of teams heading the Hilliard for a large soccer tourney dealing with the &lt;i&gt;Roundabout of Doom&lt;/i&gt; planned for the triangle at Scioto-Darby, Main and Cemetary Roads?  I dread dealing with roundabouts and I'd hate to put unsuspecting teams from &lt;a href="http://en.wikipedia.org/wiki/Pennsyltucky"&gt;Pennsyltucky&lt;/a&gt; through that.&lt;br /&gt;&lt;br /&gt;Either way, as a current HCSD resident, overall I think this is a good thing.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-5528227923680029766?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RQa7dfk1ueZXkrhw4ympHzqwxps/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RQa7dfk1ueZXkrhw4ympHzqwxps/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RQa7dfk1ueZXkrhw4ympHzqwxps/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RQa7dfk1ueZXkrhw4ympHzqwxps/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=vEI9LJD9"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=BTHmZCOk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=uacP8rm6"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=uacP8rm6" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=lATyKq1B"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=lATyKq1B" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=6AozpewR"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=6AozpewR" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/lmVNTnJN_kc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/5528227923680029766/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=5528227923680029766" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5528227923680029766?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/5528227923680029766?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/lmVNTnJN_kc/hilliard-to-gain-crew-facility.html" title="Hilliard to gain Crew Facility" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/05/hilliard-to-gain-crew-facility.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IHQ3c-fCp7ImA9WxdTFEg.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-8886057557251342991</id><published>2008-05-10T18:45:00.001-04:00</published><updated>2008-05-10T18:45:32.954-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-10T18:45:32.954-04:00</app:edited><title>Where'd WCSN go?</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Columbus Sports Network disappeared from the Clear QAM channel 85-7 on Time Warner Columbus last week.  I was hoping it would reappear but I haven't found it so far.&lt;br/&gt;&lt;br/&gt;&lt;a href='http://www.hdcolumbus.net/vb-hdtv/showthread.php?t=3990'&gt;This thread&lt;/a&gt; is helpful in finding the QAM listings on TWC, but it's not up to date...since WCSN is gone.  I'm guessing they decided to encrypt it, which really makes no sense since you can pick the channel up OTA.  I thought that by law, they have to make this signal available through the "lifeline service", which means it should be unscrambled.&lt;br/&gt;&lt;br/&gt;QAM has tended to work better than my downstairs TV with the cable box, so I was hoping that it would reappear in time for the Crew game tonight.  I'm no longer holding my breath.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-8886057557251342991?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/E-GMGOnRmi10_i_xxNqwHgbfpEU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E-GMGOnRmi10_i_xxNqwHgbfpEU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/E-GMGOnRmi10_i_xxNqwHgbfpEU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E-GMGOnRmi10_i_xxNqwHgbfpEU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=dDPGi6Bl"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=bODl3Ehn"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=NIYq3num"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=NIYq3num" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=DSF043gR"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=DSF043gR" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=QuJlDgY9"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=QuJlDgY9" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/4fLlfml_L8Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/8886057557251342991/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=8886057557251342991" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/8886057557251342991?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/8886057557251342991?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/4fLlfml_L8Q/where-wcsn-go.html" title="Where&amp;#39;d WCSN go?" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/05/where-wcsn-go.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMDRXc-eCp7ImA9WxdTFEg.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-3522772077834055396</id><published>2008-05-10T16:47:00.001-04:00</published><updated>2008-05-10T16:47:54.950-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-10T16:47:54.950-04:00</app:edited><title>Trophy Manager Firefox Plugin</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;This is old news to those who browse the US/Canada board on &lt;a href='http://www.trophymanager.com'&gt;TrophyManager.com&lt;/a&gt;, but I figured I'd stick something out here just in case someone's searching the net for information about the old Greasemonkey scripts.&lt;br/&gt;&lt;br/&gt;&lt;a href='http://code.google.com/p/trexma-for-firefox/'&gt;trexma-for-firefox&lt;/a&gt; is a new project hosted at Google Code.  At version 0.5, it currently implements all functionality available in the GM scripts with the exception of the training graph literals.  Since Trophymanager implemented the cool flash graph, that scrape is no longer needed.&lt;br/&gt;&lt;br/&gt;If you want to use trexma for firefox, go to the aforementioned project, and download trexma_0.5.xpi.  Open this file with Firefox, and it should install the extension into your browser.&lt;br/&gt;&lt;br/&gt;Enjoy!  &lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-3522772077834055396?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jHkN_77GPuCTGSEk0M_JxxthmMw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jHkN_77GPuCTGSEk0M_JxxthmMw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jHkN_77GPuCTGSEk0M_JxxthmMw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jHkN_77GPuCTGSEk0M_JxxthmMw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=ItTWv2MU"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=SsJFFS0E"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=YfFOTdx2"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=YfFOTdx2" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=jE05b6Lm"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=jE05b6Lm" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=2C1ZLZyz"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=2C1ZLZyz" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/aTPjm5fjfEQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/3522772077834055396/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=3522772077834055396" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3522772077834055396?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3522772077834055396?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/aTPjm5fjfEQ/trophy-manager-firefox-plugin.html" title="Trophy Manager Firefox Plugin" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/05/trophy-manager-firefox-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4DRH08fCp7ImA9WxZaF04.&quot;"><id>tag:blogger.com,1999:blog-6958306.post-3040929885074299755</id><published>2008-05-01T22:12:00.001-04:00</published><updated>2008-05-02T08:22:55.374-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-02T08:22:55.374-04:00</app:edited><title>The thing about perception</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Doug MacLean had an interesting quote on 590 in TO regarding the late John McConnell's perception of him courtesy of &lt;a href='http://blog.dispatch.com/cbj/2008/05/say_it_aint_so_doug.shtml'&gt;Puckrakers&lt;/a&gt;:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;I went back and I coached in Columbus for a year. I was the president, I was the general manager, I was running the rink, I was trying to get the Rolling Stones to play in our building … I mean, I just had too many hats. Mr. McConnell, God bless him, but he thought I was running a high school basketball team, if the truth was known. He had no idea of the size of the operation, that it really was running an NHL team and a building and everything.&lt;/blockquote&gt;If true, then Doug is responsible.  In business, you are responsible for marketing yourself and making sure that your boss understands what you do and how good you are at it.  If your boss doesn't "get it"  then it is up to you to change the message and educate until they do.  &lt;br/&gt;&lt;br/&gt;It can be a tough lesson to learn, but ultimately, you have to take some responsibility over marketing yourself and make adjustments when needed.&lt;br/&gt;&lt;br/&gt;&lt;div class='blogger-post-footer'&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;&lt;/script&gt;&lt;br/&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&amp;gt;&lt;br/&gt;&lt;/script&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7737529800615990";
/* RSS Ad, created 2/26/08 */
google_ad_slot = "0334624276";
google_ad_width = 468;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958306-3040929885074299755?l=twofourone.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hAylMafF_1vTeBGgsw4w8NaJI1U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hAylMafF_1vTeBGgsw4w8NaJI1U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hAylMafF_1vTeBGgsw4w8NaJI1U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hAylMafF_1vTeBGgsw4w8NaJI1U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=Nw6vuYVE"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=7stFx6hs"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=rEfmElyy"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=rEfmElyy" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=sHOaM1Ea"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=sHOaM1Ea" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TwoFourOne?a=HfmiVS21"&gt;&lt;img src="http://feeds.feedburner.com/~f/TwoFourOne?i=HfmiVS21" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TwoFourOne/~4/-xjCWuQeIAo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://twofourone.blogspot.com/feeds/3040929885074299755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=6958306&amp;postID=3040929885074299755" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3040929885074299755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6958306/posts/default/3040929885074299755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TwoFourOne/~3/-xjCWuQeIAo/thing-about-perception.html" title="The thing about perception" /><author><name>Mike</name><uri>http://www.blogger.com/profile/04074103559645856043</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="07229901267959410008" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://twofourone.blogspot.com/2008/05/thing-about-perception.html</feedburner:origLink></entry></feed>
