<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-36759899</id><updated>2011-07-31T02:13:54.485+01:00</updated><category term='Virtual Machine'/><category term='Cryptography'/><category term='Google Maps'/><category term='System'/><category term='RHEL'/><category term='OSGi'/><category term='Performance'/><category term='Technology'/><category term='Troubleshooting'/><category term='Hibernate'/><category term='Software Pattern'/><category term='Java Debugging'/><category term='Security'/><category term='Java Profiling'/><category term='TCP/IP'/><category term='JeOS'/><category term='Java'/><category term='RIA'/><category term='Collection'/><category term='Google App Engine'/><category term='Ajax'/><category term='Google'/><category term='Web Scraping'/><category term='Web service'/><category term='Web'/><category term='Testing'/><category term='C++'/><category term='Life'/><category term='Tomcat'/><category term='JMX'/><category term='Travel'/><category term='DSL'/><category term='Eclipse'/><category term='Grimoires'/><category term='Apache web server'/><category term='Ubuntu'/><category term='Shibboleth'/><category term='Parallel Computing'/><category term='JavaScript'/><category term='P2P'/><category term='JSPWiki'/><category term='Grid Computing'/><category term='News'/><category term='Thought'/><title type='text'>Weijian's Technical Notes</title><subtitle type='html'>Separate concerns. - Edsger Wybe Dijkstra</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>97</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-36759899.post-1259950935359955685</id><published>2010-03-31T21:29:00.003+01:00</published><updated>2010-03-31T21:33:35.101+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Two Useful Eclipse Plugins</title><content type='html'>&lt;a href="http://findbugs.sourceforge.net/"&gt;FindBugs&lt;/a&gt; uses static analysis       to  look for bugs       in Java code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://antlrv3ide.sourceforge.net/"&gt;ANTLR IDE&lt;/a&gt; provides support for &lt;a href="http://www.antlr.org/"&gt;ANTLR&lt;/a&gt; parser generator.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1259950935359955685?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1259950935359955685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1259950935359955685' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1259950935359955685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1259950935359955685'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2010/03/two-useful-eclipse-plugins.html' title='Two Useful Eclipse Plugins'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5875123189139025400</id><published>2010-02-06T20:09:00.002Z</published><updated>2010-02-06T20:14:58.295Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>1&lt;&lt;32 = ?</title><content type='html'>Let 1 be a 32 bit integer in Java, what should 1&amp;lt;&amp;lt;32 be?&lt;br /&gt;&lt;br /&gt;0? Because the "1" bit will be shifted to the far left?&lt;br /&gt;&lt;br /&gt;In fact, it is 1. See in &lt;a href="http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.19"&gt;the Java programming spec&lt;/a&gt;, "If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator &amp;amp; with the mask value 0x1f. The shift distance actually used is therefore always in the range 0 to 31, inclusive." So &amp;lt;&amp;lt; can be considered as a cyclic left shift operation, the bits shifted on the left end will reappear on the right end.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5875123189139025400?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5875123189139025400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5875123189139025400' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5875123189139025400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5875123189139025400'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2010/02/1.html' title='1&amp;lt;&amp;lt;32 = ?'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6398443971930416600</id><published>2010-01-18T21:38:00.005Z</published><updated>2010-01-18T23:13:37.795Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><title type='text'>Ways of Implementing DSL</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;DSL&lt;/span&gt;, &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_language"&gt;domain-specific language&lt;/a&gt;, or simply our very own language intended to solve our own specific problem, may not be limited to a programming or scripting language, it can also be, for instance, a file format, or a network protocol. In any case, the language has a syntax which defines the legal vocabulary in the language, and a grammar which defines rules of composing words in the vocabulary to meaningful sentences and paragraphs. So in order to understand the language and to take the right action based on the language, what we need are a lexer that translates language stream into token stream, and a parser that maps tokens to the grammar rules.&lt;br /&gt;&lt;br /&gt;There are many ways of implementing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;DSL&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;First, if the language is really simple, we can just code the lexer and parser manually. I.e., manually separate character stream into tokens, and manually construct an &lt;a href="http://en.wikipedia.org/wiki/LL_parser"&gt;LL&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/LL_parser"&gt;recursive descent parser&lt;/a&gt;. Obviously this method won't work well if the language becomes complex.&lt;br /&gt;&lt;br /&gt;Second, make the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;DSL&lt;/span&gt; an XML language. For instance, &lt;a href="http://en.wikipedia.org/wiki/BPEL"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;BPEL&lt;/span&gt;&lt;/a&gt; is a web service &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;workflow&lt;/span&gt; language. Though &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;BPEL&lt;/span&gt; is nothing more than an XML language, it surely can fulfill complex tasks. The advantages of making &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;DSL&lt;/span&gt; as XML are: first we can use XML schema (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;XSD&lt;/span&gt;) to design the language, so we can also use XML schema validation to validate if something is valid according to the schema;  second there are mature and popular tools for validating and parsing XML possibly in every &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;progamming&lt;/span&gt; languages.&lt;br /&gt;&lt;br /&gt;Third, we can go to the conventional way to design a complex language, i.e., to use a parser generator, such as &lt;a href="http://en.wikipedia.org/wiki/Antlr"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;Antlr&lt;/span&gt;&lt;/a&gt;. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Antlr&lt;/span&gt; is implemented in Java, but it can be used to generate code in many other languages  than Java, such as C++, Python, C# ... One of the reasons for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;Antlr&lt;/span&gt; is quite popular is that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;Antlr&lt;/span&gt; has a very sophisticated tooling for designing, visualising and even debugging grammar: &lt;a href="http://www.antlr.org/works/index.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;AntlrWorks&lt;/span&gt;&lt;/a&gt;, which is quite impressive.&lt;br /&gt;&lt;br /&gt;We can even combine the above two methods together when designing a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;DSL&lt;/span&gt;. For instance, &lt;a href="http://en.wikipedia.org/wiki/XSL_Transformations"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;XSLT&lt;/span&gt;&lt;/a&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;XSL&lt;/span&gt; Transformation, is an XML-based language for transforming XML documents into other documents.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt; XSLT&lt;/span&gt; makes use of &lt;a href="http://en.wikipedia.org/wiki/XPath"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;XPath&lt;/span&gt;&lt;/a&gt;, which can be implemented using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;Antlr&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Fourth, nowadays, modern dynamic languages like Ruby and &lt;a href="http://en.wikipedia.org/wiki/Groovy_%28programming_language%29"&gt;Groovy&lt;/a&gt; can be used to implement many &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;DSLs&lt;/span&gt;.       Because such &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;DSLs&lt;/span&gt; will live inside Groovy, they have to obey &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;Groovy's&lt;/span&gt; grammar rules. Compared to languages implemented using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;Antlr&lt;/span&gt;, their flexibility is somehow restricted. See &lt;a href="http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages"&gt;here&lt;/a&gt; for an introduction to designing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;DSL&lt;/span&gt; with Groovy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6398443971930416600?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6398443971930416600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6398443971930416600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6398443971930416600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6398443971930416600'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2010/01/ways-of-implementing-dsl.html' title='Ways of Implementing DSL'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2477134339577732735</id><published>2010-01-10T23:12:00.003Z</published><updated>2010-01-10T23:38:28.877Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TCP/IP'/><title type='text'>Protocol Verification Using Tcpdump and Wireshark</title><content type='html'>It is a must to use&lt;a href="http://runtime32.blogspot.com/2009/12/capture-and-analyse-network-packets.html"&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Tcpdump&lt;/span&gt; (to capture) and/or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Wireshark&lt;/span&gt; (to analyse)&lt;/a&gt; to verify protocol implementation when doing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;TCP&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;IP&lt;/span&gt; network programming.&lt;br /&gt;&lt;br /&gt;First, it can verify if the message sent by me is as intended, thus it can expose any bug in my protocol implementation. Today a bug has been found in this sense: I use Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;DataOutputStream&lt;/span&gt;.write(int) to send a short, so only the lowest byte of the short has been sent.&lt;br /&gt;&lt;br /&gt;Second, it can detect any inconsistency between the protocol specification, i.e., what I think the message should look like, and the actual messages that are sent by the other party, i.e., out of my control. Today, several inconsistencies have been found in this way. For instance, the length of a message (a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;TCP&lt;/span&gt; packet) is different from that defined in the spec. Clearly the spec in my hand is out of dated.&lt;br /&gt;&lt;br /&gt;Without Tcpdump and Wireshark, I would be like walking in the dark when implementing my protocol.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2477134339577732735?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2477134339577732735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2477134339577732735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2477134339577732735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2477134339577732735'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2010/01/protocol-verification-using-tcpdump-and.html' title='Protocol Verification Using Tcpdump and Wireshark'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7732365850696808512</id><published>2009-12-29T23:31:00.004Z</published><updated>2010-01-10T10:20:15.550Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TCP/IP'/><title type='text'>Capture and Analyse Network Packets</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Tcpdump"&gt;tcpdump&lt;/a&gt; is the standard packet capturing facility available on most Linux systems, which is based on command line. &lt;a href="http://en.wikipedia.org/wiki/Wireshark"&gt;Wireshark&lt;/a&gt;, formerly called Ethereal, is another popular packet capturing facility, free and GUI-based. Both tcpdump and Wireshark are based on &lt;a href="http://en.wikipedia.org/wiki/Libpcap"&gt;pcap&lt;/a&gt;, so it is possible to combine them in capturing and analysing network packets, to take advantages of both.&lt;br /&gt;&lt;br /&gt;For instance, I use the following tcpdump command to capture the traffic to and from www.google.com using http protocol:&lt;br /&gt;&lt;br /&gt;sudo tcpdump -i wlan0 -w td.dat -nnvvXSs 1514 host www.google.com&lt;br /&gt;&lt;br /&gt;Note:&lt;br /&gt;sudo: It may require root privilege to capture packets.&lt;br /&gt;-i wlan0: By default tcpdump captures packets on the eth0 interface. Since I am using wireless, I need to specify the wireless interface wlan0. When using VPN, the interface should be ppp0 instead usually.&lt;br /&gt;-w td.dat: write all captured packets to the file td.dat.&lt;br /&gt;-nn: no hostname and port resolving.&lt;br /&gt;-vv: very verbose.&lt;br /&gt;-X: print in both hex and ascii.&lt;br /&gt;-S: absolute sequence.&lt;br /&gt;-s 1514:  &lt;code&gt;&lt;/code&gt;tcpdump takes the first 68 bytes of data from a packet by default. Here the first 1514 bytes are taken.&lt;br /&gt;host www.google.com: this is the expression which says capturing packets whose dst host or src host is www.google.com.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://danielmiessler.com/study/tcpdump/"&gt;this tcpdump tutorial&lt;/a&gt; for more info about tcpdump usage.&lt;br /&gt;&lt;br /&gt;Now Wireshark can be used to analyse the captured packets by tcpdump. Here Wireshark's GUI is exploited.&lt;br /&gt;&lt;br /&gt;Use Wireshark to open td.dat, and apply the preset http filter. The http traffic can be easily browsed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7732365850696808512?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7732365850696808512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7732365850696808512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7732365850696808512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7732365850696808512'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/12/capture-and-analyse-network-packets.html' title='Capture and Analyse Network Packets'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6691596828934220360</id><published>2009-12-12T13:49:00.002Z</published><updated>2009-12-12T14:09:45.093Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Buzzwords in Job Descriptions</title><content type='html'>In these days, I am looking at job descriptions for senior Java developer position. Here is the list of buzzwords appearing inside. The list will grow when I come across more buzzwords.&lt;br /&gt;&lt;a href="http://jakarta.apache.org/jmeter/"&gt;&lt;br /&gt;JMeter&lt;/a&gt;: a Java framework for measuring server performance. Server types include Web, Web service, database (via JDBC), LDAP, JMS, mail (POP3 ...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Selenium_%28software%29"&gt;Selenium&lt;/a&gt;: a Firefox extension that allows composing web tests inside Firefox, replaying tests and generating tests in many different programming languages such as Java, C#, Ruby, Groovy ... This is a good example for what extra functionalities Firefox extension can bring to the browser.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6691596828934220360?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6691596828934220360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6691596828934220360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6691596828934220360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6691596828934220360'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/12/buzzwords-in-job-descriptions.html' title='Buzzwords in Job Descriptions'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6253820098457482090</id><published>2009-12-05T22:07:00.003Z</published><updated>2009-12-05T22:52:16.300Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Memory Overhead of Java Objects</title><content type='html'>First, each Java object has two implicit references: one to its monitor (lock), the other to its &lt;a href="http://en.wikipedia.org/wiki/Virtual_method_table"&gt;method dispatch table&lt;/a&gt;. Each reference occupies 4 bytes, so that is 8 bytes overhead.&lt;br /&gt;&lt;br /&gt;Second, byte alignment needs to be taken into consideration. On a 32-bit machine, object needs to be aligned at 4-byte boundary. On a 64-bit machine, object needs to be aligned at 8-byte boundary. Nowadays, 64-bit machines become popular. For instance, my laptop has a 64-bit Intel Core 2 Duo CPU T7500.&lt;br /&gt;&lt;br /&gt;So on my laptop if I create an object that has only one byte field, then the actual size of the object will be 16 bytes. That is 93.75% overhead. If I create an object that has three int fields, then the actual size of the object will be 24 bytes. That is 50% overhead.&lt;br /&gt;&lt;br /&gt;So be very careful when creating a huge number of small objects, because significant extra memory will be required for object overhead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How to measure the size of an object&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Write a simple program consisting of an infinite loop.  Inside the loop, create the object whose size is to be measured. Then use "jmap -histo pid" to measure the size. pid is the process id of the Java program. Because the loop is infinite, it gives plenty of  time for jmap to connect to the Java process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6253820098457482090?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6253820098457482090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6253820098457482090' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6253820098457482090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6253820098457482090'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/12/memory-overhead-of-java-objects.html' title='Memory Overhead of Java Objects'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1557659372482236110</id><published>2009-10-23T15:16:00.004+01:00</published><updated>2009-10-23T15:41:26.307+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Adjustable Timer Task</title><content type='html'>Java provides &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/TimerTask.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;TimerTask&lt;/span&gt;&lt;/a&gt; for tasks that can be scheduled for one-time or repeated execution by a Timer. But it has some serious drawbacks.&lt;br /&gt;&lt;br /&gt;First, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;TimerTask&lt;/span&gt; can only be scheduled either for one-time or for repeated execution of a roughly fixed period. It can not be scheduled with changing periods, for example, at the following moments since its start: 0, 5, 6, 12, 100, 101, 102 seconds ... If it is scheduled twice, for example, first scheduled after 1 seconds, then 3 seconds after the first execution, no matter in which thread the second schedule is requested, inside or outside the Timer thread, a java.lang.IllegalStateException: Task already scheduled or cancelled will be thrown.&lt;br /&gt;&lt;br /&gt;Second, each &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;TimerTask&lt;/span&gt; is served with an individual background thread. Thus it makes &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;TimerTask&lt;/span&gt; not a very scalable solution if a lot of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;TimerTasks&lt;/span&gt; are needed but each of them is not very heavy weighted.&lt;br /&gt;&lt;br /&gt;Since 1.5, Java provides the java.util.concurrent package, which includes an Executor Framework. The basic idea of Executor Framework is to separate the concerns of tasks and the mechanism to execute tasks. So programmers define tasks and then leave tasks to be executed by the Executor Framework, which can be configurable to use a single thread, or a thread pool to execute the tasks.&lt;br /&gt;&lt;br /&gt;The following Java code illustrates how to use &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;ScheduledExecutorService&lt;/span&gt;&lt;/a&gt; to implement adjustable timer task.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Test {&lt;br /&gt;&lt;br /&gt; static private &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ScheduledExecutorService&lt;/span&gt; scheduler =&lt;br /&gt;     Executors.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;newSingleThreadScheduledExecutor&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt; static private Runnable pig = new Runnable() {&lt;br /&gt;     public void run() {&lt;br /&gt;         System.out.println("This is pig");&lt;br /&gt;         scheduler.schedule(this, 1,&lt;br /&gt;            &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;TimeUnit&lt;/span&gt;.SECONDS);&lt;br /&gt;     };&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; static private Runnable bear = new Runnable() {&lt;br /&gt;     Random random = new Random();&lt;br /&gt;     public void run() {&lt;br /&gt;         System.out.println("This is bear");&lt;br /&gt;         scheduler.schedule(this,&lt;br /&gt;            2 + random.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;nextInt&lt;/span&gt;(3),&lt;br /&gt;            &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;TimeUnit&lt;/span&gt;.SECONDS);&lt;br /&gt;     };&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * @param &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;args&lt;/span&gt;&lt;br /&gt;  */&lt;br /&gt; public static void main(String[] &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;args&lt;/span&gt;) {&lt;br /&gt;     scheduler.schedule(pig, 0, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;TimeUnit&lt;/span&gt;.SECONDS);&lt;br /&gt;     scheduler.schedule(bear, 0, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;TimeUnit&lt;/span&gt;.SECONDS);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1557659372482236110?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1557659372482236110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1557659372482236110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1557659372482236110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1557659372482236110'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/10/adjustable-timer-task.html' title='Adjustable Timer Task'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1940994913434483227</id><published>2009-10-21T14:42:00.003+01:00</published><updated>2009-10-21T15:03:44.613+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grid Computing'/><title type='text'>Globus Toolkit's Future</title><content type='html'>Today Ian Foster sent out &lt;a href="http://www.mail-archive.com/gt-user@lists.globus.org/msg01336.html"&gt;an email&lt;/a&gt; about Globus' future plans, which contains many interesting points.&lt;br /&gt;&lt;br /&gt;First, a GRAM5 (for job submission) will come out as a replacement for both GRAM2 (old fashion) and GRAM4 (web service based). It confirms my feeling that web service based job submission such as GridSAM does not pick up enough users. The old fashion job submission just can not be retired at this moment.&lt;br /&gt;&lt;br /&gt;Second, the Java web service core will be re-implemented to leverage state-of-the-art technologies. &lt;a href="http://cxf.apache.org/"&gt;Apache CXF&lt;/a&gt; is selected as the web service development kit. See &lt;a href="http://confluence.globus.org/display/whi/WSDK+Evaluation"&gt;here&lt;/a&gt; for a very informative comparison between several popular latest the web service development kits including Apache CXF, &lt;a href="http://ws.apache.org/axis2/"&gt;Apache Axis2&lt;/a&gt; and &lt;a href="https://jax-ws.dev.java.net/"&gt;Metro&lt;/a&gt; (the JAX-WS RI). Apache CXF is favored over Apache Axis2 because Axis2 uses proprietary deployment model and lacks the support for IoC containers such as Spring Framework.&lt;br /&gt;&lt;br /&gt;Third, globus.org will provide RFT (reliable file transfer) online service, which provides reliable, high-performance, end-to-end, fire-and-forget data transfer. globus.org has moved into the era of cloud computing!&lt;br /&gt;&lt;br /&gt;Fourth, MDS (monitoring and discovery service) will be refactored to separate monitoring and service/resource discovery. Monitoring will be left to mature dedicated monitor softwares. MDS itself will focus on acting as a service registry. I certainly agree this decision since it favors the idea of separating concerns. The recently published GLUE2 spec still mixes up monitoring data and service metadata for discovery. It is interesting to see if the future development of GLUE will reflect the decision made on MDS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1940994913434483227?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1940994913434483227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1940994913434483227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1940994913434483227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1940994913434483227'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/10/globus-toolkits-future.html' title='Globus Toolkit&apos;s Future'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-600339429234950250</id><published>2009-10-15T14:51:00.002+01:00</published><updated>2009-10-15T15:00:39.561+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Jar Service Provider</title><content type='html'>&lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html"&gt;Jar File Spec&lt;/a&gt; provides a simple &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider"&gt;service provider mechanism&lt;/a&gt;: a provider configuration file is located inside META-INF/services/, with the service interface or abstract class name as the configuration file name, which contains the list of implementing class names. Java 1.6 has a &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html"&gt;ServiceLoader&lt;/a&gt; class for looking up service providers.&lt;br /&gt;&lt;br /&gt;It will be handy to define a well known interface, and to use the provider configuration file to list all implementations. Thus at runtime, ServiceLoader can be used to iterate all available service providers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-600339429234950250?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/600339429234950250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=600339429234950250' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/600339429234950250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/600339429234950250'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/10/jar-service-provider.html' title='Jar Service Provider'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8510652856362560832</id><published>2009-09-14T20:54:00.003+01:00</published><updated>2009-09-14T21:05:16.312+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Set up HTTP Cookie in Java</title><content type='html'>In my Java programming, I need to set up some pre-defined HTTP cookie so that I can tell the website what content I prefer on using HttpURLConnection, for example. This is what I do:&lt;br /&gt;&lt;br /&gt;// Create my cookie&lt;br /&gt;HttpCookie cookie = new HttpCookie("cookie_name", "cookie_value");&lt;br /&gt;// So that the cookie applies to all pages&lt;br /&gt;cookie.setPath("/");&lt;br /&gt;     &lt;br /&gt;CookieManager cookieManager = new CookieManager();&lt;br /&gt;cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);&lt;br /&gt;     &lt;br /&gt;CookieStore cookieStore = cookieManager.getCookieStore();&lt;br /&gt;cookieStore.add(uri, cookie);&lt;br /&gt;     &lt;br /&gt;// Set my cookie manager that contains my cookie to be used system-wide&lt;br /&gt;CookieHandler.setDefault(cookieManager);&lt;br /&gt;&lt;br /&gt;// From now on my cookie will be used for all connections to the web site denoted by uri.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8510652856362560832?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8510652856362560832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8510652856362560832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8510652856362560832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8510652856362560832'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/09/set-up-http-cookie-in-java.html' title='Set up HTTP Cookie in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7085940136463128762</id><published>2009-08-26T14:56:00.003+01:00</published><updated>2009-08-26T15:10:27.246+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Scraping'/><title type='text'>Web Scraping in Java</title><content type='html'>There are at least three ways to do &lt;a href="http://en.wikipedia.org/wiki/Web_scraping"&gt;web scraping&lt;/a&gt; in Java.&lt;br /&gt;&lt;br /&gt;First, "manually" use string matching and regular expression to extract information from downloaded HTML.&lt;br /&gt;&lt;br /&gt;Second, use &lt;a title="JTidy" href="http://jtidy.sourceforge.net/index.html" id="achd"&gt;JTidy&lt;/a&gt; to transform HTML to XHTML, and then use XQuery (e. g., &lt;a title="Saxon" href="http://en.wikipedia.org/wiki/Saxon_XSLT" id="uvlx"&gt;Saxon&lt;/a&gt;, &lt;a title="..." href="http://www.w3.org/XML/Query/#implementations" id="dlpw"&gt;...&lt;/a&gt;) over XHTML to extract required information.&lt;br /&gt;&lt;br /&gt;Third, which is what I prefer:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create a &lt;a title="TagSoup" href="http://home.ccil.org/%7Ecowan/XML/tagsoup/" id="gf-u"&gt;TagSoup&lt;/a&gt; HTML parser, which provides an SAX interface;&lt;/li&gt;&lt;li&gt;Use &lt;a href="http://www.xom.nu/"&gt;XOM&lt;/a&gt; to build a DOM from HTML using the TagSoup SAX parser;&lt;/li&gt;&lt;li&gt;Use the built-in XPath query facility inside XOM (i.e., Jaxen) to parse the XOM DOM document.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;A sample code skeleton looks like:&lt;br /&gt;&lt;br /&gt;// Create a TagSoup SAX parser.&lt;br /&gt;XMLReader parser = new org.ccil.cowan.tagsoup.Parser();&lt;br /&gt;     &lt;br /&gt;// Use the TagSoup parser to build an XOM document from HTML.&lt;br /&gt;Document doc = new Builder(parser).build(new File("index.html"));&lt;br /&gt;     &lt;br /&gt;// Do some XPath query: find all "table" elements.&lt;br /&gt;Nodes nodes = doc.query("//*[local-name()='table']");&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="..." href="http://www.w3.org/XML/Query/#implementations" id="dlpw"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7085940136463128762?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7085940136463128762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7085940136463128762' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7085940136463128762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7085940136463128762'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/08/web-scraping-in-java.html' title='Web Scraping in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3088888815674776647</id><published>2009-07-08T14:42:00.009+01:00</published><updated>2009-07-09T15:45:34.569+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JMX'/><title type='text'>Tomcat Admin Web App and JMX</title><content type='html'>Tomcat has provided an Admin webapp, which sits inside $CATALINA_HOME/server/webapps in order to access classes contained in Tomcat jars, to make it easy to configure webapps, for instance, to add a DataSource to a webapp.&lt;br /&gt;&lt;br /&gt;As seen from its soource code, the Admin webapp simply creates &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/jmx/overview/JMXoverviewTOC.html"&gt;JMX&lt;/a&gt; MBeans (managed bean), and save them to a MBean server. Tomcat MBean server then rewrites Tomcat server.xml and webapps/&lt;span style="font-style: italic;"&gt;webapp&lt;/span&gt;/META-INF/context.xml.&lt;br /&gt;&lt;br /&gt;The JMX Remote API specification details &lt;a href="http://download.java.net/jdk7/docs/technotes/guides/jmx/overview/lookup.html#wp997177"&gt;how&lt;/a&gt; an LDAP server can be used to store and retrieve information about JMX connectors exposed by JMX agents. JNDI is used to talk to an LDAP server.&lt;br /&gt;&lt;br /&gt;MBeans can be viewed in the MBeans tab of jconsole.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further digging on MBeans in Tomcat&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;All key constructs in Tomcat, such as Server, Engine, Host and Context, are implemented as MBeans, see package org.apache.catalina.core.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Since Tomcat makes use of &lt;a href="http://commons.apache.org/modeler/apidocs/org/apache/commons/modeler/package-summary.html#package_description"&gt;Apache Commons Modeler&lt;/a&gt; to deliver the Model MBean support, mbeans-descriptors.xml (read by Apache Commons Modeler) appears in many packages that contain MBeans.&lt;/li&gt;&lt;li&gt;Tomcat uses the MBean server implementation provided by JVM.&lt;/li&gt;&lt;li&gt;The Server and Context MBeans support operations to store their configurations, which are delegated to the StoreConfig MBean that implements the logic of rewriting various Tomcat configuration files, see package org.apache.catalina.storeconfig in container/modules/storeconfig.&lt;/li&gt;&lt;li&gt;org.apache.catalina.storeconfig implements a StoreConfigLifecycleListener that registers the StoreConfig MBean right after Tomcat is started. StoreConfigLifecycleListener is configured in Tomcat server.xml.&lt;/li&gt;&lt;/ul&gt;The information above is based on Tomcat 5.5.27.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3088888815674776647?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3088888815674776647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3088888815674776647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3088888815674776647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3088888815674776647'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/07/tomcat-admin-web-app-jmx-and-jndi.html' title='Tomcat Admin Web App and JMX'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3977576869797575582</id><published>2009-07-07T14:22:00.011+01:00</published><updated>2009-07-08T11:58:20.971+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Troubleshooting'/><title type='text'>Troubleshooting Remote Java Application</title><content type='html'>Previously, I was using &lt;a href="http://runtime32.blogspot.com/2009/06/monitoringprofilingdebugging-java.html"&gt;SSH+VPN&lt;/a&gt; to reduce the task of troubleshooting a remote Java application to the task of troubleshooting a local Java application. This is a generic approach, but has its own disadvantages. One of them is that sometimes the proper debugging/profiling/monitoring tools can not be run in remote machine due to the restraints in the deployment environment. In that case, we have to run tools locally and perform a genuine remote troubleshooting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Remote jconsole&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To start a Java application that supports remote jconsole is easy: just add the following into Java command line arguments:&lt;br /&gt;&lt;br /&gt;-Dcom.sun.management.jmxremote.port=&lt;span style="font-style: italic;"&gt;portNum &lt;/span&gt;-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false&lt;br /&gt;&lt;br /&gt;Then we can ask jconsole to simply connect to &lt;span style="font-style: italic;"&gt;hostname:portNum&lt;/span&gt;, given that a firewall is not set up on the remote machine.&lt;br /&gt;&lt;br /&gt;jconsole uses JMX which is built on RMI. The &lt;span style="font-style: italic;"&gt;portNum&lt;/span&gt; we specify  is the port number used by the RMI registry. The actural RMI connection will be opened using another port that can not be specified as a Java command line argument.  When the firewall on the remote machine is disabled, and the local jconsole is successfully connected to the remote Java application, we can use "lsof -p &lt;span style="font-style: italic;"&gt;pid&lt;/span&gt; | grep TCP" to check which port is used by RMI.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://forums.sun.com/thread.jspa?forumID=58&amp;amp;threadID=717761"&gt;this&lt;/a&gt; and &lt;a href="http://forums.sun.com/thread.jspa?forumID=58&amp;amp;threadID=703567"&gt;that&lt;/a&gt; for a programmatic approach to get jconsole through the firewall. It basically starts up a customised RMI registry that open a RMI channel on a pre-defined port, which is implemented as a &lt;a href="http://java.sun.com/javase/6/docs/api/index.html?java/lang/instrument/package-summary.html"&gt;Java Agent&lt;/a&gt;. &lt;a href="http://blogs.sun.com/jmxetc/entry/connecting_through_firewall_using_jmx"&gt;Here&lt;/a&gt; is an almost "official" tutorial to achieve that.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Remote jvisualvm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First of all, according to VisualVM's document,  VisualVM can retrieve monitoring information on remote applications but it cannot          profile remote applications. VisualVM requires jstatd running on the remote machine. Since jstatd is based on RMI, so VisualVM suffers from the same issue as jconsole when facing firewall.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Remote YourKit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Maybe it is easier to set up &lt;a href="http://www.yourkit.com/download/index.jsp"&gt;YourKit Java profiler&lt;/a&gt; to troubleshoot a remote Java application. And YourKit is claimed to be so lightweight that it can be used when the application is running in the production mode.&lt;br /&gt;&lt;br /&gt;YourKit provides &lt;a href="http://www.yourkit.com/docs/80/help/profiling_j2ee_remote.jsp"&gt;some means&lt;/a&gt; to integrate with a remote JEE/servlet container, such as Tomcat, JBoss, WebSphere, WebLogic ... For Tomcat, the integration creates a startup_with_yjp.sh based on startup.sh, which simply adds the following magic Java options:&lt;br /&gt;&lt;br /&gt;"-agentpath:&lt;yjp_home&gt;&lt;span style="font-style: italic;"&gt;YJP_HOME&lt;/span&gt;/bin/linux-x86-32/libyjpagent.so=disablestacktelemetry,&lt;br /&gt;disableexceptiontelemetry,delay=10000,&lt;br /&gt;port=16666,sessionname=Tomcat"&lt;br /&gt;&lt;br /&gt;"port=&lt;span style="font-style: italic;"&gt;portNum&lt;/span&gt;" can be used to specified a number instead of the default 10001. To connect the remote Java application with YourKit agent turned on, simply ask to connect to &lt;span style="font-style: italic;"&gt;serverName:portNum&lt;/span&gt; in the local YourKit UI. Since all profiling data go in the specified port number, it is easy to set up an SSH tunnel if that port is blocked by firewall.&lt;br /&gt;&lt;br /&gt;More investigation needs to be done to understand the profiling overhead given that setting.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/yjp_home&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3977576869797575582?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3977576869797575582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3977576869797575582' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3977576869797575582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3977576869797575582'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/07/troubleshooting-remote-java-application.html' title='Troubleshooting Remote Java Application'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-721915653829804110</id><published>2009-06-29T11:08:00.002+01:00</published><updated>2009-06-29T11:23:10.240+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java Profiling'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='Troubleshooting'/><title type='text'>More on Java Troubleshooting</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;JDK&lt;/span&gt; has provided better and better troubleshooting facilities, among &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/index.html"&gt;other tools&lt;/a&gt;. Obviously they are extremely important to develop serious Java applications, which usually have to offer specified performance under resource restraint.&lt;br /&gt;&lt;br /&gt;These tools include&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;jinfo&lt;/span&gt;&lt;/span&gt; &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;pid&lt;/span&gt;&lt;/span&gt; : check Java command line options and system properties.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;jstack&lt;/span&gt;&lt;/span&gt; &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;pid&lt;/span&gt;&lt;/span&gt; : print thread's stack the their status (e.g., blocking on some object). This is great for knowing what's going on inside the Java application at &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;runtime&lt;/span&gt;. And there is no need to set up &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;JVM&lt;/span&gt; specially for this &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;purpse&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;jvisualvm&lt;/span&gt;&lt;/span&gt; : profile and monitor Java process. It seems &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;JDK&lt;/span&gt; on Linux has &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;jvisualvm&lt;/span&gt; by default. But you need to install &lt;a href="https://visualvm.dev.java.net/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;jvisualvm&lt;/span&gt;&lt;/a&gt; separately on Windows.&lt;/li&gt;&lt;/ul&gt;as well as some other tools already mentioned before:&lt;br /&gt;&lt;ul&gt;&lt;li style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;jconsole&lt;/span&gt;&lt;/li&gt;&lt;li style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;jmap&lt;/span&gt;&lt;/li&gt;&lt;li style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;jhat&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-721915653829804110?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/721915653829804110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=721915653829804110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/721915653829804110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/721915653829804110'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/more-on-java-troubleshooting.html' title='More on Java Troubleshooting'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-125503044677246963</id><published>2009-06-25T15:16:00.005+01:00</published><updated>2009-07-01T12:18:52.597+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='System'/><title type='text'>Clean up Harddisk before Dispose of Computer</title><content type='html'>After 3 years' working as a heater, my Sony VAIO laptop is finally retiring. There is one critical task that must be done before it can be disposed of: cleaning up its harddisk. Since I graduated from a computer lab that researched and developed one of the very first harddisks in China, I long know not only deleted files but also overwritten files can be recovered. Nevertheless, &lt;a href="http://linuxhelp.blogspot.com/2006/06/how-to-securely-erase-hard-disk-before.html"&gt;this blog&lt;/a&gt; as well as its comments still give me a lot of information. There are some useful points:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;On Linux, &lt;span style="font-weight: bold;"&gt;shred &lt;/span&gt;can be used to clean up disk. By default it overwrites the harddisk for 25 times. Call it like this: &lt;span style="font-weight: bold;"&gt;shred -vz /dev/hda&lt;/span&gt; (-z: finally overwrite with all zero to disguise the shred process.)&lt;/li&gt;&lt;li&gt;Or, use &lt;a href="http://www.dban.org/"&gt;DBAN&lt;/a&gt;, which is used by many governments. DBAN stands for "Darik's Boot And Nuke". The software is a boot CD/DVD image that is used to boot the computer and then do the cleaning up.&lt;/li&gt;&lt;li&gt;Here is &lt;a href="http://www.cs.auckland.ac.nz/%7Epgut001/pubs/secure_del.html"&gt;the seminal paper&lt;/a&gt; describing the theory behind securely deleting harddisk data.&lt;/li&gt;&lt;/ul&gt;It will be useful to know how long it takes for shred or DBAN to process a harddisk of a certain size.&lt;br /&gt;&lt;br /&gt;On my &lt;a href="http://vaio.sony.co.uk/view/ShowProduct.action?product=VGN-SZ3XWP%2FC&amp;amp;productFilters=retired&amp;amp;site=voe_en_GB_cons&amp;amp;pageType=Overview&amp;amp;category=VN+SZ+Series"&gt;Sony VAIO VGN-SZ3XWP/C&lt;/a&gt;, shred takes about 3.5 hours to 4 hours to run a random pass of a 39 GiB disk partition! A random pass overwrites the disk with random bits. Not sure how random it is. The 1st and the 13th (possibly the last one, the 25th pass) passes are random passes. The other passes use different short fixed pattern to overwrite. Each costs about half an hour.&lt;br /&gt;&lt;br /&gt;Further updates for running "shred -vz /dev/sda" on a 94GiB harddisk. The 1st, 13th and 25th passes are using random data generated from /dev/urandom. The other passes write fixed but different bit patterns. It takes 49h33m26s to finish.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-125503044677246963?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/125503044677246963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=125503044677246963' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/125503044677246963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/125503044677246963'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/clean-up-harddisk-before-dispose.html' title='Clean up Harddisk before Dispose of Computer'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1530588622544762589</id><published>2009-06-22T20:59:00.002+01:00</published><updated>2009-06-22T21:16:43.439+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>IDE for C++</title><content type='html'>I may work on a C++ project in future. So I am looking for an IDE for C++. I know A good IDE can double the productivity of programming.&lt;br /&gt;&lt;br /&gt;Unlike Java, C++ is not cross platform and has many variants though it does have a standard. Thus which IDE to choose is dependent on which C++ to use.&lt;br /&gt;&lt;br /&gt;On Windows, Microsoft Visual Studio is the choice for Visual C++ :)&lt;br /&gt;&lt;br /&gt;I would like to choose Eclipse &lt;a href="http://www.eclipse.org/cdt/"&gt;CDT&lt;/a&gt; for GNU C++. CDT is only IDE. To build and debug C++ code, CDT requires external &lt;a href="http://en.wikipedia.org/wiki/Toolchain"&gt;toolchain&lt;/a&gt;, e.g., &lt;a href="http://en.wikipedia.org/wiki/GNU_toolchain"&gt;GNU toolchain&lt;/a&gt;. CDT on Liunx will automatically pick up GNU toolchain, which usually is there. But to make CDT on Windows work, we need to install &lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt; (Minimalist GNU for Windows). &lt;a href="http://max.berger.name/howto/cdt/ar01s03.jsp#wincompiler"&gt;Here&lt;/a&gt; is a good tutorial on installing MinGW. Once MinGW is properly installed and added into PATH, CDT can pick up MinGW as a toolchain automatically.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1530588622544762589?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1530588622544762589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1530588622544762589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1530588622544762589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1530588622544762589'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/ide-for-c.html' title='IDE for C++'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4744111471105099782</id><published>2009-06-19T14:11:00.002+01:00</published><updated>2009-06-19T16:10:57.776+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Troubleshooting OutOfMemoryError</title><content type='html'>When a large running Java application throws out an OutOfMemoryError, it indicates either the existence of a memory leak bug, or simply the fact that the maximum heap size has been reached. Don't panic, it is straightforward to do troubleshooting.&lt;br /&gt;&lt;br /&gt;Most importantly, DO NOT SHUTDOWN the problematic JVM. Keep the crime scene.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/share/jmap.html"&gt;jmap&lt;/a&gt; to dump the heap. Under JDK 1.5, the dumped heap, in the format of hprof, is always put under the home directory and under the name "heap.bin". In addition, jmap can also be used to show the heap object histogram, a quick way to see the classes occupying the most space.&lt;/li&gt;&lt;li&gt;Use &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/share/jhat.html"&gt;jhat&lt;/a&gt; to analyze the heap dumped by jmap. If the heap is dumped by a JDK 1.5 jmap, invoke jhat (that is only available in JDK6+) in this way: jhat -J-mxNm -stack false heap_dump_file. "-stack false" turns off tracking object allocation call stack because the allocation site information is not available in the heap           dump. N should be larger than the maximum heap size used when running the problematic Java process. jhat takes quite some time to analyze the heap dump.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="options"&gt;&lt;/a&gt;jhat starts up a web server after finishes analyzing the heap dump. Now we can use a browser to point to the jhat web server, and find out who use up all the memory.&lt;/li&gt;&lt;li&gt;At the very end of the front page, click the link "Show heap histogram". it takes quite some time to generate the histogram.&lt;/li&gt;&lt;li&gt;In the histogram, the classes whose instances occupy most of the heap can be easily identified. Obviously they are suspects of the crime.&lt;/li&gt;&lt;li&gt;Clicking one of the suspects brings us to the page showing the referers of the suspect. In this way, we can track down which part of our code hold references to objects that use up heap. Now by using our knowledge of the program logic, the problem cause can be finally located.&lt;/li&gt;&lt;/ol&gt;See, the method is staightforward. All we need is patience and a good understanding of the source code in order to find the problem cause.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4744111471105099782?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4744111471105099782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4744111471105099782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4744111471105099782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4744111471105099782'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/troubleshooting-outofmemoryerror.html' title='Troubleshooting OutOfMemoryError'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4439886675805500430</id><published>2009-06-12T11:38:00.003+01:00</published><updated>2009-06-12T12:23:49.428+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><title type='text'>Direction+</title><content type='html'>I am working on a web app, &lt;a href="http://direction-plus.appspot.com/"&gt;Direction+&lt;/a&gt;, running on &lt;a href="http://appengine.google.com/"&gt;Google App Engine for Java&lt;/a&gt;. Yes, it is another direction service that suggests a driving route based on your chosen source and destination. But it has some add-on features as its name suggests: Direction Plus.&lt;br /&gt;&lt;br /&gt;First, you can personalise Direction+ by providing your car's information, in particular, the fuel consumption measurement of your car, for urban cycle, extra-urban cycle and combined cycle.  Thus, when calculating the route, Direction+ is also able to calculate how much fuel you will use and how much it costs (based on the fuel price you set). The fuel consumption calculation is measured on each individual step of the route. For instance, driving on a motor way will be much more fuel-efficient than driving in the city center. Isn't it good to know the cost of the driving before hand? In addition, the calculation is done in your own browser and your personalisation is stored in your browser as a cookie. So there is no privacy concern at all.&lt;br /&gt;&lt;br /&gt;Second, Direction+ is a mashup that combines Google Maps Service and BBC travel news service together. When a driving route is calculated, the travel news, e. g., accidents news, along the route are displayed as well on the map. Isn't it good to know the traffic situation before driving? Currently too many travel news are returned especially when the route is very long, efforts are being made to improve the algorithm of filtering the not-so-relevant news.&lt;br /&gt;&lt;br /&gt;How quick is Direction+ updated with BBC travel news? Please see &lt;a href="http://direction-plus.appspot.com/monitorNewsDB"&gt;its status page&lt;/a&gt;. A complete update takes about 30 minutes. For instance, at the time of writing, the last update took 26 minutes to finish. It read 2297 news from BBC, among which only 50 happened after the previous update, and among the 50 news that newly happened, 12 have cached coordinate in the data store. So though the number of news is large, Direction+ manages to reduce the communication to a small amount.&lt;br /&gt;&lt;br /&gt;One of the tricky things about GAE for java is that every servlet request must be served within 30 seconds. So the update of news is implemented in an incremental and on-the-fly way:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Incremental&lt;/span&gt;: the complete update is divided into many small steps, and each step can be finished in a controlled time slot;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;On-the-fly&lt;/span&gt;: the news updated in each small step is available immediately, long before the complete update is done.&lt;/li&gt;&lt;/ul&gt;Direction+ is designed for UK users because I live in UK. Enjoy it and let me know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4439886675805500430?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4439886675805500430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4439886675805500430' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4439886675805500430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4439886675805500430'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/direction.html' title='Direction+'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5947949748693944859</id><published>2009-06-08T11:43:00.003+01:00</published><updated>2009-06-08T12:04:15.696+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java Profiling'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debugging'/><title type='text'>Monitoring/Profiling/Debugging Java Process Remotely</title><content type='html'>Usually there are two difficulties involved:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;How to communicate between the remote (target) machine and the local (console) machine? This varies per monitoring/profiling/debugging method. E.g., the built-in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;JMX&lt;/span&gt;&lt;/span&gt; console (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;jconsole&lt;/span&gt;&lt;/span&gt;) uses remote &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;RMI&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;How to penetrate the firewall if existing?&lt;/li&gt;&lt;/ol&gt;The generic approach is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Know how to do it locally;&lt;/li&gt;&lt;li&gt;Run a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;vncserver&lt;/span&gt;&lt;/span&gt; on the remote machine (In fact, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;vncserver&lt;/span&gt;&lt;/span&gt; is lightweight, and easy to install in case there is no &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;vncserver&lt;/span&gt;&lt;/span&gt; installed on the remote machine);&lt;/li&gt;&lt;li&gt;Use ssh to set up a tunnel between the remote machine and the local machine, e.g., ssh -L&lt;span style="font-style: italic;"&gt;&lt;/span&gt;5901:remote_machine:5901 userid@remote_machine (ssh is very user-friendly w.r.t. firewall);&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Start a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;vnc&lt;/span&gt;&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;verview&lt;/span&gt;&lt;/span&gt; locally, pointing to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;localhost&lt;/span&gt;&lt;/span&gt;:1, and follow the procedure established in step 1.&lt;/li&gt;&lt;/ol&gt;In this way, remote monitoring/profiling/debugging tasks are doable following a step-by-step procedure.&lt;br /&gt;&lt;br /&gt;Of course, sometimes, there is no need to set up a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;vncserver&lt;/span&gt; as long as the communication between the remote machine and the local machine is done in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;TCP&lt;/span&gt; and the port number is known.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5947949748693944859?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5947949748693944859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5947949748693944859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5947949748693944859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5947949748693944859'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/06/monitoringprofilingdebugging-java.html' title='Monitoring/Profiling/Debugging Java Process Remotely'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-634640951679272983</id><published>2009-05-29T11:53:00.003+01:00</published><updated>2009-05-29T12:08:38.954+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Logging in Java</title><content type='html'>Yes, this is a very basic issue in Java programming, but sometimes it can be really confusing to find where the logs are and how to declaratively configure what to log.&lt;br /&gt;&lt;br /&gt;Log4j is widely used and is configured using log4j.properties. But some programmers choose to use Apache commons logging instead of using log4j API directly. Commons logging is a thin-wrapper for other pluggable logging tools, such log4j and Sun logging facility. &lt;a href="http://commons.apache.org/logging/guide.html#Configuration"&gt;The configuration guide&lt;/a&gt; of commons logging describes a five step procedure to find the underlying logging mechanism, among which, step 3 says:&lt;br /&gt;&lt;br /&gt;"If the Log4J logging system is available in the application class path, use the corresponding wrapper class (&lt;a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Log4JLogger.html"&gt;Log4JLogger&lt;/a&gt;)."&lt;br /&gt;&lt;br /&gt;In other words, usually even commons logging API is used in the program, the actual logging service is provided by log4j. Thus log4j.properties is used to configure how logging should be done.&lt;br /&gt;&lt;br /&gt;Another logging configuration file is &lt;a href="http://www.javapractices.com/topic/TopicAction.do?Id=143"&gt;logging.properties&lt;/a&gt;, which is used by java.util.logging.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-634640951679272983?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/634640951679272983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=634640951679272983' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/634640951679272983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/634640951679272983'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/05/logging-in-java.html' title='Logging in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8451908400368148424</id><published>2009-05-28T23:02:00.002+01:00</published><updated>2009-05-28T23:26:43.666+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Best Java Decompiler</title><content type='html'>Recently I am working on a UK e-Science project which uses &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;BPEL&lt;/span&gt; to orchestrate web services and submits computational jobs to a &lt;a href="http://www.cs.wisc.edu/condor/"&gt;condor&lt;/a&gt; pool. The source code of some of those web services is missing (great!), so I have to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;decompile&lt;/span&gt; the class files in order to make necessary changes.&lt;br /&gt;&lt;br /&gt;In my pursuit of the "best" java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;decompiler&lt;/span&gt;, I first tried &lt;a href="http://java.decompiler.free.fr/"&gt;JD&lt;/a&gt;. It is free. But in my use case, it generates some Java code that can not be compiled. Then I tried &lt;a href="http://members.fortunecity.com/neshkov/dj.html"&gt;DJ&lt;/a&gt;. It is good, but it only allows for 10 free trials. Each invocation of DJ is considered to be one trial. After that you have to purchase it.&lt;br /&gt;&lt;br /&gt;I hadn't been very happy &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;until&lt;/span&gt; I found &lt;a href="http://en.wikipedia.org/wiki/JAD_%28JAva_Decompiler%29"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Jad&lt;/span&gt;&lt;/a&gt;. Jad did my job. And it turns out that Jad is behind many Java decompiler GUIs such as DJ, &lt;a href="http://www.bysoft.se/sureshot/cavaj/"&gt;Cavaj&lt;/a&gt;, and &lt;a href="http://jadclipse.sourceforge.net/wiki/index.php/Main_Page"&gt;JadClipse&lt;/a&gt;, an Eclipse plugin. I am quite happy with Jad even without a GUI to drive it.&lt;br /&gt;&lt;br /&gt;It is interesting to see JD and Jad were implemented in C++. Won't it be better for Java programmers to have a Java decompiler written in Java?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8451908400368148424?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8451908400368148424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8451908400368148424' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8451908400368148424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8451908400368148424'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/05/best-java-decompiler.html' title='Best Java Decompiler'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-613766409025407584</id><published>2009-05-04T15:06:00.005+01:00</published><updated>2009-05-04T15:30:35.362+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Subversive Problem</title><content type='html'>I am using &lt;a href="http://www.eclipse.org/subversive/"&gt;Subversive&lt;/a&gt; - the Eclipse subversion &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;plugin&lt;/span&gt; - 0.7.7 plus its subversion connector 2.1.0.&lt;br /&gt;&lt;br /&gt;Today an exception jumped out of nowhere, making all my subversion based projects unable to synchronise with the server.&lt;br /&gt;&lt;br /&gt;java.lang.NoSuchMethodError: org.eclipse.team.svn.core.connector.SVNChangeStatus.&lt;init&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;IJJJLjava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;IIIIZZLjava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;JZLjava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;Ljava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;JLorg&lt;/span&gt;/eclipse/team/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;svn&lt;/span&gt;/core/connector/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;SVNLock&lt;/span&gt;;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;JJILjava&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;lang&lt;/span&gt;/String;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;ZZLorg&lt;/span&gt;/eclipse/team/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;svn&lt;/span&gt;/core/connector/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;SVNConflictDescriptor&lt;/span&gt;;)V&lt;br /&gt;   at org.tigris.subversion.javahl.ConversionUtility.convert(ConversionUtility.java:287)&lt;br /&gt;   at org.tigris.subversion.javahl.ConversionUtility$4.doStatus(ConversionUtility.java:146)&lt;br /&gt;   at org.tigris.subversion.javahl.SVNClient.status(Native Method)&lt;br /&gt;   at org.polarion.team.svn.connector.javahl.JavaHLConnector.status(JavaHLConnector.java:406)&lt;br /&gt;   at org.eclipse.team.svn.core.extension.factory.ThreadNameModifier.status(ThreadNameModifier.java:606)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.SVNUtility.status(SVNUtility.java:330)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.SVNUtility.getSVNInfoForNotConnected(SVNUtility.java:803)&lt;br /&gt;   at org.eclipse.team.svn.core.SVNTeamProvider.uploadRepositoryResource(SVNTeamProvider.java:241)&lt;br /&gt;   at org.eclipse.team.svn.core.SVNTeamProvider.connectToProject(SVNTeamProvider.java:172)&lt;br /&gt;   at org.eclipse.team.svn.core.SVNTeamProvider.getRepositoryResource(SVNTeamProvider.java:71)&lt;br /&gt;   at org.eclipse.team.svn.core.svnstorage.SVNRemoteStorage.loadLocalResourcesSubTreeSVNImpl(SVNRemoteStorage.java:628)&lt;br /&gt;   at org.eclipse.team.svn.core.svnstorage.SVNRemoteStorage.loadLocalResourcesSubTree(SVNRemoteStorage.java:521)&lt;br /&gt;   at org.eclipse.team.svn.core.svnstorage.SVNRemoteStorage.getRegisteredChildren(SVNRemoteStorage.java:273)&lt;br /&gt;   at org.eclipse.team.svn.core.synchronize.AbstractSVNSubscriber.resourcesStateChangedImpl(AbstractSVNSubscriber.java:212)&lt;br /&gt;   at org.eclipse.team.svn.core.synchronize.AbstractSVNSubscriber.resourcesStateChanged(AbstractSVNSubscriber.java:169)&lt;br /&gt;   at org.eclipse.team.svn.core.svnstorage.SVNRemoteStorage$3.runImpl(SVNRemoteStorage.java:152)&lt;br /&gt;   at org.eclipse.team.svn.core.operation.AbstractActionOperation.run(AbstractActionOperation.java:77)&lt;br /&gt;   at org.eclipse.team.svn.core.operation.LoggedOperation.run(LoggedOperation.java:38)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.ProgressMonitorUtility.doTask(ProgressMonitorUtility.java:104)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.ProgressMonitorUtility.doTaskExternal(ProgressMonitorUtility.java:90)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.ProgressMonitorUtility$1$1.run(ProgressMonitorUtility.java:60)&lt;br /&gt;   at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1800)&lt;br /&gt;   at org.eclipse.team.svn.core.utility.ProgressMonitorUtility$1.run(ProgressMonitorUtility.java:58)&lt;br /&gt;   at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)&lt;br /&gt;&lt;br /&gt;The only possible reason that I can think of is I accidentally copied some ".&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;svn&lt;/span&gt;" directories into some non-subversion-based project.&lt;br /&gt;&lt;br /&gt;On eclipse.technology.subversive Newsgroup, there is &lt;a href="http://www.eclipse.org/newsportal/article.php?id=1185&amp;amp;group=eclipse.technology.subversive#1185"&gt;a discussion&lt;/a&gt; on the same exception, but happen on Subversive 0.7.8.&lt;br /&gt;&lt;br /&gt;I am very lucky since after I changed the subversion connector in use from Native &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;JavaHL&lt;/span&gt; to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;SVN&lt;/span&gt; Kit, the problem seems gone! Otherwise, all my development work has to stop!&lt;/init&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-613766409025407584?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/613766409025407584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=613766409025407584' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/613766409025407584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/613766409025407584'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/05/subversive-problem.html' title='Subversive Problem'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5383332321832305659</id><published>2009-04-27T16:00:00.008+01:00</published><updated>2009-04-27T22:35:47.881+01:00</updated><title type='text'>MVC Practice in Browser Application</title><content type='html'>I am working on a &lt;a href="http://runtime32.blogspot.com/2009/04/browser-application.html"&gt;browser application&lt;/a&gt;, called &lt;a href="http://users.ecs.soton.ac.uk/wf/dplus/"&gt;Direction+&lt;/a&gt;. I am trying to enforce the &lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;MVC&lt;/a&gt; pattern in order to achieve better code manageability. Basically, it is all about separating concerns.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;View&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All presentation goes into HTML code. Better no HTML code generated in JavaScript. Furthermore, style is separated into CSS. For the concern of performance, CSS could be embedded into HTML to save a pair of request and response.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Model&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The states should be kept in JavaScript structs, objects or variables. HTML markups SHOULD NOT be used to store any state other than user input. Using HTML markup for non-user-input state, for instance, a hidden field in form, is a necessary communication mechanism between browser and web server, but not necessary in a browser application.&lt;br /&gt;&lt;br /&gt;By keeping all states in JavaScript, it can be assured to only have a single copy of state in a centralised place and the HTML view is purely a presentation of the state.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Controller&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Business logic is implemented in JavaScript. A minimal set of code, which are basically event handlers, are embedded into HTML, as entry points into the business logic.&lt;br /&gt;&lt;br /&gt;JavaScript should be written in an object-oriented style.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5383332321832305659?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5383332321832305659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5383332321832305659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5383332321832305659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5383332321832305659'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/mvc-practice-in-browser-application.html' title='MVC Practice in Browser Application'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-799606607981245069</id><published>2009-04-22T21:27:00.002+01:00</published><updated>2009-04-22T21:46:10.362+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><title type='text'>Override Tomcat Session Cookie</title><content type='html'>Tomcat uses &lt;a href="http://en.wikipedia.org/wiki/Http_cookie"&gt;HTTP cookie&lt;/a&gt; to track browser sessions. By default Tomcat 5.5 generates session cookies without an expiration date (Expires=...), like:&lt;br /&gt;&lt;br /&gt;Set-Cookie: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;JSESSIONID&lt;/span&gt;=A39F8F3623D20&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;EF&lt;/span&gt;9E66D309E298E87E0; Path=/&lt;br /&gt;&lt;br /&gt;using &lt;a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/Cookie.html#setMaxAge%28int%29"&gt;Cookie.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;setMaxAge&lt;/span&gt;(-1)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Without an expiration date, this cookie should be deleted by the browser when it is closed, which is what IE7 does. Thus, even the session has a lifetime, say 12 hours, at the Tomcat side, if the browser was restarted, the session would be lost.&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Firefox&lt;/span&gt; keeps the session cookie when it restarts.&lt;br /&gt;&lt;br /&gt;I use the following code to override this behavior:&lt;br /&gt;&lt;br /&gt;// after users log in&lt;br /&gt;// &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;HttpServletResponse&lt;/span&gt; response&lt;br /&gt;response.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;setHeader&lt;/span&gt;("Set-Cookie", "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;JSESSIONID&lt;/span&gt;=" + request.getSession().getId()&lt;br /&gt;                + "; Expires=" + &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;getCookieExpiresFormat&lt;/span&gt;().&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;formatByAge&lt;/span&gt;(age)&lt;br /&gt;                + "; Path=/");&lt;br /&gt;&lt;br /&gt;It generates something like&lt;br /&gt;&lt;br /&gt;Set-Cookie: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;JSESSIONID&lt;/span&gt;=A39F8F3623D20&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;EF&lt;/span&gt;9E66D309E298E87E0; Expires=Thu, 22-Apr-2010 20:07:56 GMT; Path=/&lt;br /&gt;&lt;br /&gt;Thus the session can be kept live for any time period even when browser restarted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-799606607981245069?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/799606607981245069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=799606607981245069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/799606607981245069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/799606607981245069'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/override-tomcat-session-cookie.html' title='Override Tomcat Session Cookie'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7798024310930342293</id><published>2009-04-21T15:13:00.004+01:00</published><updated>2009-04-21T15:45:21.770+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>JavaScript and Multi-Threading</title><content type='html'>Several internet sources, such as &lt;a href="http://odetocode.com/Blogs/scott/archive/2007/01/08/9734.aspx"&gt;this&lt;/a&gt;, suggest that JavaScript in browser, runs in a single thread that is also responsible for updating browser UI; and JavaScript code is triggered by events. If this is true, it is not a surprise to see why AJAX has to be &lt;a href="http://www.w3schools.com/ajax/ajax_xmlhttprequest.asp"&gt;asynchronous&lt;/a&gt;, otherwise network IO will block the browser UI, i.e., make the UI irresponsible.&lt;br /&gt;&lt;br /&gt;There were/are several activities to make JavaScript multi-threaded. For instance, the popular JavaScript toolkit &lt;a href="http://www.dojotoolkit.org/"&gt;Dojo&lt;/a&gt; has some support for &lt;a href="http://api.dojotoolkit.org/jsdoc/1.3/dojox.timing"&gt;multi-threading&lt;/a&gt;. And there is even a &lt;a href="http://www.google.co.uk/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=8&amp;amp;url=http%3A%2F%2Fjsthread.sourceforge.net%2Fcgi-bin%2Fwiki%2Fwiki.cgi%3Faction%3DATTACH%26page%3DDocument%26file%3Dthesis-en.pdf&amp;amp;ei=KdTtSbmTHJSZjAeAkd0K&amp;amp;usg=AFQjCNFTf8fMbI_m1Mc7KzcjhJQ4gW2EMg&amp;amp;sig2=dNRoLYARBxGOitQWKNWSOQ"&gt;paper&lt;/a&gt; talking about multi-threading in JavaScript.&lt;br /&gt;&lt;br /&gt;JavaScript now really becomes a serious programming language. Not only there are a lot of libraries/frameworks available so that programmers do not need to write everything from scratch, but also there are a very good programming support, such as profiling (YUI), unit testing (YUI), logging (YUI), debugging (&lt;a href="http://www.mozilla.org/en/projects/venkman/"&gt;Venkman&lt;/a&gt; for Firefox and for &lt;a href="http://www.jonathanboutelle.com/mt/archives/2006/01/howto_debug_jav.html"&gt;Microsoft Script Editor&lt;/a&gt; for IE).&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7798024310930342293?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7798024310930342293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7798024310930342293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7798024310930342293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7798024310930342293'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/javascript-and-multi-threading.html' title='JavaScript and Multi-Threading'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-777635208659727319</id><published>2009-04-20T11:33:00.003+01:00</published><updated>2009-04-20T12:17:08.886+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>Browser Application</title><content type='html'>I am working on a &lt;span style="font-style: italic;"&gt;browser application&lt;/span&gt;, which I already made some good progress and will put online after it is refactored in object oriented JavaScript.&lt;br /&gt;&lt;br /&gt;What I called browser application should have the following three characteristics.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A browser application's runtime environment consists of a web browser and internet only. So if you can surf the net, you can run it. Of course nothing prevents it from being deployed on a web server for people to access. Note. in that case, the web server is not required to have any extra support except static HTTP hosting.&lt;/li&gt;&lt;li&gt;A browser application uses &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;AJAX&lt;/a&gt; to provide functionalities. With so many powerful AJAX APIs around on the internet, a browser application can have some amazing functionalities.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A browser application can easily be a rich internet application given that now JavaScript, as well as other client side technologies, have already become so rich in terms of presentation capability.&lt;/li&gt;&lt;/ol&gt;In summary, a browser application is a browser (&lt;span style="font-style: italic;"&gt;only&lt;/span&gt;) based rich internet application using AJAX.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-777635208659727319?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/777635208659727319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=777635208659727319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/777635208659727319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/777635208659727319'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/browser-application.html' title='Browser Application'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-49237864580570111</id><published>2009-04-06T16:32:00.002+01:00</published><updated>2009-04-06T16:42:47.243+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java Profiling'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debugging'/><title type='text'>Check Java Thread CPU Usage</title><content type='html'>Today I came across a question: if an application occupies 100% CPU time, and its source code is extremely large so that reading its source code to find what is going on may not be an option; what should we do to find out the problem?&lt;br /&gt;&lt;br /&gt;Let's assume the application is written in Java.&lt;br /&gt;&lt;br /&gt;First, we can use &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html"&gt;jstack&lt;/a&gt; combined with &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/share/jps.html"&gt;jps&lt;/a&gt; to print out threads' stack trace, which gives us a good idea about which methods are being executed.&lt;br /&gt;&lt;br /&gt;We can also use jconsole with &lt;a href="http://blogs.sun.com/lmalventosa/entry/per_thread_cpu_usage_jconsole"&gt;some plugin&lt;/a&gt; to display threads' CPU usage. The jconsole plugin is based on JTop (&lt;code&gt;&lt;jdk6_home&gt;/demo/management/JTop).&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-49237864580570111?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/49237864580570111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=49237864580570111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/49237864580570111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/49237864580570111'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/check-java-thread-cpu-usage.html' title='Check Java Thread CPU Usage'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7063577057520327117</id><published>2009-04-06T13:15:00.002+01:00</published><updated>2009-04-06T13:21:24.298+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Add to Version Control before Commit</title><content type='html'>I am using Eclipse 3.4.2 Ganymede plus Subversive 0.7.7. If I try to commit some newly added files, i.e., they are not under subversion control yet, Eclipse simply becomes irresponsive.&lt;br /&gt;&lt;br /&gt;New files MUST be added into version control first, before they can be committed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7063577057520327117?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7063577057520327117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7063577057520327117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7063577057520327117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7063577057520327117'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/04/add-to-version-control-before-commit.html' title='Add to Version Control before Commit'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5835130598770722899</id><published>2009-03-09T15:29:00.004Z</published><updated>2009-03-10T10:05:24.123Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Machine'/><title type='text'>Invalid Virtual Machine</title><content type='html'>Today I tried to add a VMware VM created by a VMware workstation to my VMware Server 2 on Windows, but failed because it was considered to be invalid. VMware server told me "either the vmx file is corrupted or the VM was created using a newer version of VMware product." Seems both were not the case.&lt;br /&gt;&lt;br /&gt;However, it turns out the vmx file could really be "corrupted". In vmx, the first line is&lt;br /&gt;&lt;pre&gt;.encoding = "windows-1252"&lt;/pre&gt;After change it to be&lt;br /&gt;&lt;pre&gt;.encoding = "UTF-8"&lt;/pre&gt; The VM is no longer considered to be invalid.&lt;br /&gt;&lt;br /&gt;Then after I changed the "numvcpus" from 2 to 1, the VM is able to run on my VMware server, which unfortunately only has one single core CPU.&lt;br /&gt;&lt;br /&gt;But interestingly, the original VM can run on a VMware server 2 on Linux.&lt;br /&gt;&lt;br /&gt;I also need to change VM's network to be NAT instead of Bridged, and restart VM, to enable networking.&lt;br /&gt;&lt;br /&gt;The guideline is that the virtual hardware for a particular Guest OS, such as the number of CPUs and the network type, has to be compatible with the hardware spec of the VMware server installation. For instance, you can not run a 2-CPU VM on a VMware server supporting only one CPU; and if there is no DHCP on the bridged network, then not surprisingly the VM can not acquire an IP if using the bridged network.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5835130598770722899?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5835130598770722899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5835130598770722899' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5835130598770722899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5835130598770722899'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/03/invalid-virtual-machine.html' title='Invalid Virtual Machine'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1663186425112705404</id><published>2009-03-04T16:01:00.003Z</published><updated>2009-03-04T16:17:34.750Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>JMeter</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T3RexjHEbhs/Sa6noKMLGqI/AAAAAAAAArU/UQVvVKYOfsE/s1600-h/jmeter.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_T3RexjHEbhs/Sa6noKMLGqI/AAAAAAAAArU/UQVvVKYOfsE/s400/jmeter.PNG" alt="" id="BLOGGER_PHOTO_ID_5309365319088413346" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jakarta.apache.org/jmeter/"&gt;Apache &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;JMeter&lt;/span&gt;&lt;/a&gt; is a GUI that allows to compose a performance test without writing a single line of code! Basically what needs to do, in order to implement a performance test, is to properly insert test components such as "thread group, "loop control", "http requests" and "performance data graph", into the test plan. Of course the parameters of these test components should be specified, for instance, how many iterations of the http request are wanted. Then simply start it and a curve as well as data is presented!&lt;br /&gt;&lt;br /&gt;With the help of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;JMeter&lt;/span&gt;, I am able to tell in a very simple test, when 27 &lt;a href="http://tuckey.org/urlrewrite/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;urlrewrite&lt;/span&gt;&lt;/a&gt; rules are enabled, the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;OMII&lt;/span&gt;-UK website has a throughput of 3030.915 per minute, i.e., 19.796 ms per request; when rules disable, the throughput is 3005.259 per minute, i.e., 19.965 ms per request. In other words, in this setting, where &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;urlrewrite&lt;/span&gt; 2.6 is used, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;urlrewrite&lt;/span&gt; rules pose a 0.9% slowdown.  Though the credibility of this particular test result needs to be established.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1663186425112705404?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1663186425112705404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1663186425112705404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1663186425112705404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1663186425112705404'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/03/jmeter.html' title='JMeter'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T3RexjHEbhs/Sa6noKMLGqI/AAAAAAAAArU/UQVvVKYOfsE/s72-c/jmeter.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2927824069252481189</id><published>2009-03-04T10:42:00.005Z</published><updated>2009-03-04T11:07:58.266Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>A Portlet Class Loading Scheme</title><content type='html'>According &lt;a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#72007"&gt;JVM Spec 5.3 Creation and Loading&lt;/a&gt;, there are two situations for a class D to load or to initiate loading another class C: either there are references to C in D's constant pool, or D creates C using reflection. In either case, if D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C.&lt;br /&gt;&lt;br /&gt;Let's assume the portal framework is a web application, and it has the following directory structure:&lt;br /&gt;&lt;pre&gt;WEB-INF/&lt;br /&gt;    classes/&lt;br /&gt;    lib/&lt;br /&gt;    portlets/&lt;br /&gt;            portlet1/&lt;br /&gt;                    classes/&lt;br /&gt;                    lib/&lt;br /&gt;            portlet2/&lt;br /&gt;                    classes/&lt;br /&gt;                    lib/&lt;br /&gt;&lt;/pre&gt;The web application class loader W will create a portlet class loader P for each portlet, that has W as its parent class loader and is responsible to load classes from portletx/classes and portletx/lib. W will use P to instantiate a portlet entry point using reflection. From the portlet entry point, all required classes will be then loaded by P, but still following the delegation model. It means W will try to load class first, only after that fails, P will load.&lt;br /&gt;&lt;br /&gt;This scheme does not violate Servlet Spec 2.4, which states "The Web application class loader must load classes from the WEB-INF/ classes directory first, and then from library JARs in the WEB-INF/lib directory. Also, any requests from the client to access the resources in WEB-INF/ directory must be returned with a SC_NOT_FOUND(404) response." It does not prevent loading class from elsewhere.&lt;br /&gt;&lt;br /&gt;The advantages of such a scheme are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It takes the view that the portal framework is a web application; its portlets are just its components instead of web applications themselves.&lt;/li&gt;&lt;li&gt;It respects the class loading scheme of the web application server. The portal framework jars can be kept inside the web application, and the portlets share those jars naturally.&lt;/li&gt;&lt;li&gt;It also facilitates deploying and undeploying portlets on the fly, because the control is purely inside the portal web application.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2927824069252481189?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2927824069252481189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2927824069252481189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2927824069252481189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2927824069252481189'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/03/portlet-class-loading-scheme.html' title='A Portlet Class Loading Scheme'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-976819814103032181</id><published>2009-02-27T11:43:00.005Z</published><updated>2009-02-27T17:15:02.641Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSGi'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Embed OSGi to Monolithic Application as a Dynamic Plugin Mechanism</title><content type='html'>&lt;a href="http://www.eclipse.org/equinox/"&gt;Eclipse Equinox&lt;/a&gt; is used as OSGi framework.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Run Equinox as a standalone application&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Read &lt;a href="http://www.vogella.de/articles/OSGi/article.html"&gt;Equinox tutorial&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;C:\eclipse\plugins&gt;java -jar org.eclipse.osgi_3.3.0.v20070530.jar -console&lt;br /&gt;&lt;br /&gt;osgi&gt; install file:d:\documents\temp\plugins\org.silentsquare.osgi.test.bundle.h&lt;br /&gt;elloworld_1.0.0.jar&lt;br /&gt;Bundle id is 1&lt;br /&gt;&lt;br /&gt;osgi&gt; ss&lt;br /&gt;&lt;br /&gt;Framework is launched.&lt;br /&gt;&lt;br /&gt;id      State       Bundle&lt;br /&gt;0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530&lt;br /&gt;1       INSTALLED   org.silentsquare.osgi.test.bundle.helloworld_1.0.0&lt;br /&gt;&lt;br /&gt;osgi&gt; start 1&lt;br /&gt;Hello World!&lt;br /&gt;&lt;br /&gt;osgi&gt; ss&lt;br /&gt;&lt;br /&gt;Framework is launched.&lt;br /&gt;&lt;br /&gt;id      State       Bundle&lt;br /&gt;0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530&lt;br /&gt;1       ACTIVE      org.silentsquare.osgi.test.bundle.helloworld_1.0.0&lt;br /&gt;&lt;br /&gt;osgi&gt; close&lt;br /&gt;&lt;br /&gt;Goodbye World!&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Startup Equinox programmatically&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;See this blog article: "&lt;a href="http://www.eclipsezone.com/eclipse/forums/t93976.rhtml"&gt;Starting Equinox from a Java application&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;With org.eclipse.osgi_3.x.x.jar on classpath, which is just an ordinary jar file plus extra OSGi information, the code looks like&lt;br /&gt;&lt;pre&gt;public class App {&lt;br /&gt;   public static void main(String[] args) throws Exception {&lt;br /&gt;       String[] equinoxArgs = {"-console"};&lt;br /&gt; BundleContext context = EclipseStarter.startup(equinoxArgs,null);&lt;br /&gt; Bundle bundle = context.installBundle("http://www.eclipsezone.com/files/jsig/bundles/HelloWorld.jar");&lt;br /&gt;       bundle.start();&lt;br /&gt; for (Bundle b : context.getBundles()) {&lt;br /&gt;     System.out.println(b);&lt;br /&gt; }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The next step would be to build Grimoires XMLView over OSGi and implement each pair of translators as OSGi bundle. But classloading could be tricky: translators need to use classes in Grimoires. How?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-976819814103032181?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/976819814103032181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=976819814103032181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/976819814103032181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/976819814103032181'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/02/embed-osgi-to-monolithic-application-as.html' title='Embed OSGi to Monolithic Application as a Dynamic Plugin Mechanism'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-326659057804430734</id><published>2009-02-27T10:43:00.003Z</published><updated>2009-02-27T11:12:19.881Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSGi'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>What OSGi Can Do For Me?</title><content type='html'>Two interesting usages of &lt;a href="http://www.osgi.org/About/WhyOSGi"&gt;OSGi&lt;/a&gt; could be explored in my development context.&lt;br /&gt;&lt;br /&gt;One is to use OSGi to componentize an existing complex application. Consider the OMII-UK website. As a web application, it has 3 logical functional units: the old repository that holds projects and releases and is almost obsolete, the new web front that also reads information from database about projects and releases, and the wiki based on &lt;a href="http://www.jspwiki.org/"&gt;JSPWiki&lt;/a&gt;. It will be nice to break them into 3 OGSi bundles to take advantage of the dynamics of OSGi bundles.&lt;br /&gt;&lt;br /&gt;The other is to use OSGi to implement a dynamic extension framework for an originally monolithic application. In Grimoires, there is an XMLView interface that allows publishing any application domain specific service descriptions as long as they are in XML. Inside the implementation of XMLView, there is a pair of translators for each domain-specific description, translating to and from Grimoires' UDDI+WSDL+Metadata service description model. It will be good that we build XMLView over OGSi framework, and then each pair of translators will become an OSGi bundle. So if we want to support a new type of domain-specific service description, we add a corresponding bundle without bringing down Grimoires. If later this support is no longer needed, we remove the bundle without bringing down Grimoires.&lt;br /&gt;&lt;br /&gt;These can be done because OSGi is claimed to be &lt;span style="font-style: italic;"&gt;humble&lt;/span&gt;: it does not take over the whole JVM, and one Java application can even host multiple OSGi frameworks.&lt;br /&gt;&lt;br /&gt;According to OSGi, &lt;blockquote&gt;If you are developing software in Java then &lt;span class="wikiword"&gt;OSGi&lt;/span&gt; technology should be a logical next step because it solves many problems that you might not even be aware can be solved. The advantages of &lt;span class="wikiword"&gt;OSGi&lt;/span&gt; technology are so numerous that if you are using Java, then &lt;span class="wikiword"&gt;OSGi&lt;/span&gt; &lt;strong&gt;should&lt;/strong&gt; be in your tool chest.&lt;/blockquote&gt;This seems reasonable because componentization looks like a natural approach towards software complexity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-326659057804430734?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/326659057804430734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=326659057804430734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/326659057804430734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/326659057804430734'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/02/what-osgi-can-do-for-me.html' title='What OSGi Can Do For Me?'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3515029339243552492</id><published>2009-02-12T15:08:00.003Z</published><updated>2009-02-12T15:33:32.694Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Google Protocol Buffer</title><content type='html'>&lt;a href="http://code.google.com/p/protobuf/"&gt;Google Protocol Buffer&lt;/a&gt; can be used to serialise and deserialise structured data, either to/from a file, or to/from network. Protocol Buffer acts as a (network) protocol parser generator. It can generate a parser that understands a specific protocol format. Of course this can be implemented using a general purpose parser generator such as &lt;a href="http://www.antlr.org/"&gt;ANTLR&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Several existing solutions are available to address the same problem.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The problematic Java Serialization.&lt;/li&gt;&lt;li&gt;The DIY approach. It is surely painful in particular for complex data structure.&lt;/li&gt;&lt;li&gt;Serialise data to XML. In Java, this is supported by JAXB. The advantages of using XML as transmission format are that, XML is language independent, is platform independent, and is human readable. The disadvantage is the associated performance cost.&lt;/li&gt;&lt;/ul&gt;According to the &lt;a href="http://code.google.com/apis/protocolbuffers/docs/javatutorial.html"&gt;Protocol Buffer's tutorial for Java&lt;/a&gt;, it has several selling points:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It has bindings for Java, C++, and Python. Thus the data can be transmitted between Java, C++, and Python applications.&lt;/li&gt;&lt;li&gt;Its performance is expected to be good, because not only it is not based on XML, but also it can boost the performance by not using Java reflection.&lt;/li&gt;&lt;li&gt;As long as following certain rules, when the protocol is updated, the new code is compatible with the old code.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3515029339243552492?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3515029339243552492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3515029339243552492' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3515029339243552492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3515029339243552492'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/02/google-protocol-buffer.html' title='Google Protocol Buffer'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7212353566366162429</id><published>2009-02-03T11:26:00.003Z</published><updated>2009-02-03T11:53:32.132Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>java.lang.NullPointerException</title><content type='html'>In &lt;a href="http://runtime32.blogspot.com/2008/11/map-of-downloads.html"&gt;one of my previous blogs&lt;/a&gt;, I mentioned a map of downloads based on Google Maps API. To create such a map, first I collect IP addresses from where the downloads were initiated, then I use &lt;span class="PageHeader"&gt;&lt;a href="http://www.maxmind.com/app/geolitecity"&gt;GeoLite City&lt;/a&gt; to translate the IP address to a geographic location on the Google map. GeoLite City is a free library with Java API, but of less precision than its commercial &lt;/span&gt;counterpart.&lt;br /&gt;&lt;br /&gt;It was working fine for many month until recently it threw out the infamous java.lang.NullPointerException. NullPointerException might be the No.1 runtime exception. It is certainly for me.&lt;br /&gt;&lt;br /&gt;A little investigation explains why NullPointerException happened. When I passed an IP address to the GeoLite City library, I naively assumed that GeoLite must be able to translate it into a geographic location, thus I did not check whether the Location object returned by GeoLite is null. So I was pulished. In fact, IP address allocation is dynamic, and an outdated GeoLite City library may not contain all the IP address information.&lt;br /&gt;&lt;br /&gt;It was not rare I made such a naive mistake. The fundamental principle to avoid NullPointerException is that, when given an object reference, no matter it is from my own code or from outside my code, thinking defensively, reason the possibility that it may be null. To play safe, always check nullity.&lt;br /&gt;&lt;br /&gt;An object reference could be given as a returned value of a method invocation, as method arguments when inside a method, or as a field member of a non-null object.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7212353566366162429?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7212353566366162429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7212353566366162429' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7212353566366162429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7212353566366162429'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2009/02/javalangnullpointerexception.html' title='java.lang.NullPointerException'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4752977939537844359</id><published>2008-12-17T15:01:00.004Z</published><updated>2008-12-17T15:33:54.672Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Parallel Computing'/><title type='text'>Parallel Array Expected in Java SE7</title><content type='html'>Two &lt;span style="font-style: italic;"&gt;Year in Review&lt;/span&gt; articles on JavaWorld, &lt;a href="http://www.javaworld.com/javaworld/jw-12-2008/jw-12-year-in-review-1.html"&gt;"Java in 2008"&lt;/a&gt; and "&lt;a href="http://www.javaworld.com/javaworld/jw-12-2008/jw-12-year-in-review-2.html"&gt;What to expect in Java SE7&lt;/a&gt;", are worth reading.&lt;br /&gt;&lt;br /&gt;Among the new features expected in SE7, which is due on early 2010, the most surprising one to me is the parallel processing support. Though it is also the one I am mostly looking forward to since I get my PhD working on the topic of parallel computing and cluster computing in Java.&lt;br /&gt;&lt;br /&gt;The parallel processing support not only provides a fork and join computing paradigm that might be tuned into a &lt;a href="http://en.wikipedia.org/wiki/Mapreduce"&gt;MapReduce&lt;/a&gt; mode, but also supports &lt;span style="font-style: italic;"&gt;parallel array&lt;/span&gt;. Parallel array is a long existing feature in parallel computing languages such as &lt;a href="http://en.wikipedia.org/wiki/HPF"&gt;High Performance Fortran&lt;/a&gt;. Inspired by HPF, &lt;a href="http://www.hpjava.org/"&gt;HPJava&lt;/a&gt; supports parallel array as well.&lt;br /&gt;&lt;br /&gt;The idea of parallel array is quite simple. It represents a large-sized data array, and the array is partitioned to many parts, with each part allocated to a single process. In such a way, each process can work on its own partition of the large array in a parallel way with regard to others, thus achieving speedup.&lt;br /&gt;&lt;br /&gt;However, it                         is still under consideration whether the parallel array&lt;code&gt;&lt;/code&gt; will be included as part of the JDK in Java SE 7 or whether it will be released as an external library.                                              &lt;br /&gt;&lt;br /&gt;A parallel array code example looks like:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;// Instantiate the ForkJoinPool with a concurrency level&lt;br /&gt;ForkJoinPool fj = new ForkJoinPool(16);&lt;br /&gt;Donut[] data = ...&lt;br /&gt;ParallelArray&lt;donut&gt; donuts = new ParallelArray(fj, data);&lt;br /&gt;&lt;br /&gt;// Filter&lt;br /&gt;Ops.Predicate&lt;donut&gt; hasSprinkles = new Ops.Predicate&lt;donut&gt;() {&lt;br /&gt; public boolean op(Donut donut) {&lt;br /&gt;   return donut.hasSprinkles();&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Map from Donut -&gt; Integer&lt;br /&gt;Ops.Predicate&lt;donut&gt; daysOld = new Ops.ObjectToInt&lt;donut&gt;() {&lt;br /&gt; public int op(Donut donut) {&lt;br /&gt;   return donut.age();&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;SummaryStatistics&lt;integer&gt; summary =&lt;br /&gt; orders.withFilter(hasSprinkles)&lt;br /&gt;       .withMapping(daysOld)&lt;br /&gt;       .summary();&lt;br /&gt;&lt;br /&gt;System.out.println("with sprinkles: " + summary.size());&lt;br /&gt;System.out.println("avg age: " + summary.average());&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4752977939537844359?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4752977939537844359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4752977939537844359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4752977939537844359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4752977939537844359'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/parallel-array-expected-in-java-se7.html' title='Parallel Array Expected in Java SE7'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-9010091771608592131</id><published>2008-12-12T11:55:00.005Z</published><updated>2008-12-12T15:17:38.764Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Grimoires'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='RIA'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Use Eclipse RAP to Build Rich Internet Application</title><content type='html'>It is a pity that I had not heard of &lt;a href="http://www.eclipse.org/rap/"&gt;Eclipse RAP&lt;/a&gt; (Rich Ajax Platform) when last year I developed &lt;a href="http://twiki.grimoires.org/bin/view/Grimoires/EclipsePlugin"&gt;Grimoires Browser&lt;/a&gt;, an Eclipse RCP based client for the Grimoires Service Registry.&lt;br /&gt;&lt;br /&gt;RAP has joined the family of Eclipse UI toolkits, as existing ones such as SWT for Windows, SWT for Liunx, and SWT for Mac. In some sense, RAP can be considered as SWT for Web.&lt;br /&gt;&lt;br /&gt;RAP is ued to develop &lt;a href="http://en.wikipedia.org/wiki/Rich_Internet_application"&gt;Rich Internet Application&lt;/a&gt; (RIA). To develop an RAP-based web application, programmers are still working in Java, in SWT, and in JFace. And RAP makes sure the UI is built on top of HTML, JavaScript and Ajax. Remind you something? Yes, &lt;a href="http://code.google.com/webtoolkit/"&gt;GWT&lt;/a&gt;. There are some very good introductory articles [&lt;a href="http://www.ibm.com/developerworks/opensource/library/os-eclipse-richajax1/"&gt;1&lt;/a&gt;, &lt;a href="http://www.ibm.com/developerworks/opensource/library/os-eclipse-richajax2/"&gt;2&lt;/a&gt;] about RAP on IBM Developer Works.&lt;br /&gt;&lt;br /&gt;It is claimed that in a minimal effort, we can transform an existing RCP application to RAP; or we can even build an application which is largely independent of RAP or RCP. So it can run as both a web application and a desktop application.&lt;br /&gt;&lt;br /&gt;No doubt, RAP is the way to go to make Grimoires Browser a web application. It will then totally relieve users the pain to install some software on their machine in order to access Grimoires.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-9010091771608592131?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/9010091771608592131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=9010091771608592131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/9010091771608592131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/9010091771608592131'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/use-eclipse-rap-to-build-rich-internet.html' title='Use Eclipse RAP to Build Rich Internet Application'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7435805975387329363</id><published>2008-12-11T20:44:00.004Z</published><updated>2008-12-11T21:33:26.309Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>My Safe</title><content type='html'>&lt;span style="font-style: italic;"&gt;My Safe&lt;/span&gt; is an &lt;a href="http://www.eclipse.org/home/categories/rcp.php"&gt;Eclipse RCP&lt;/a&gt; based software I developed last year. As suggested by its name, it is a secure file manager.&lt;br /&gt;&lt;br /&gt;It is easy to use. You must input the correct password in order to enter My Safe. Inside My Safe, you can see all directories and files as they originally are. But these directories and files are encrypted in the file system. And they are decrypted on demand in My Safe's interface. The password you use to enter My Safe is the key for encryption and decryption. &lt;a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard"&gt;AES&lt;/a&gt; is used as the cipher.&lt;br /&gt;&lt;br /&gt;I want to argue that such software as My Safe is necessary even on our personal desktops or laptops. So that other people may possess our computer but can not possess our data.&lt;br /&gt;&lt;br /&gt;My Sony laptop does have a secure drive called My Safe as well, but it is not perfect. It is a proprietary technology. It means the data is tightly bound to the Sony laptop. So if the software is broken, there is no way for me to recover the encrypted data. And I can not decrypted the encrypted data on another computer.&lt;br /&gt;&lt;br /&gt;Therefore I developed my very own My Safe. And it turns out to be very useful!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7435805975387329363?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7435805975387329363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7435805975387329363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7435805975387329363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7435805975387329363'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/my-safe.html' title='My Safe'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6372660653101926727</id><published>2008-12-11T20:16:00.003Z</published><updated>2008-12-11T20:43:07.546Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Yahoo User Interface</title><content type='html'>Programming in JavaScript was very painful. You have to make sure your code is compatible with all major browsers such as IE and Firefox. Now thanks to well-developed JavaScript libraries, JavaScript programming is much more pleasant.&lt;br /&gt;&lt;br /&gt;JavaScript libraries, such as &lt;a href="http://developer.yahoo.com/yui/"&gt;Yahoo User Interface&lt;/a&gt; (YUI), &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, &lt;a href="http://www.dynamicdrive.com/"&gt;Dynamic Drive&lt;/a&gt;, and &lt;a href="http://dojotoolkit.org/"&gt;Dojo&lt;/a&gt;, not only deal with cross browser compatibility issues, but also make common tasks easy.&lt;br /&gt;&lt;br /&gt;I have used several components of YUI in developing the &lt;a href="http://www.omii.ac.uk/"&gt;OMII-UK&lt;/a&gt; website:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/reset/"&gt;CSS Reset&lt;/a&gt; (neutralizes browser CSS styles)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/base/"&gt;CSS Base&lt;/a&gt; (applies consistent style foundation for common elements)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/fonts/"&gt;CSS Fonts&lt;/a&gt; (foundation for typography and font-sizing)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/grids/"&gt;CSS Grids&lt;/a&gt; (page layout)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/yahoo/"&gt;The YAHOO Global Object&lt;/a&gt; (base requirement for all YUI components)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/dom/"&gt;DOM Collection&lt;/a&gt; (convenience methods for DOM interactions)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/event/"&gt;Event Utility&lt;/a&gt; (event normalization and custom events)&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/button/"&gt;Button&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/tabview/"&gt;TabView&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;BTW, &lt;a href="http://browsershots.org/"&gt;browsershots.org&lt;/a&gt; allows you to see how your website looks like in tens of browsers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6372660653101926727?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6372660653101926727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6372660653101926727' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6372660653101926727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6372660653101926727'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/yahoo-user-interface.html' title='Yahoo User Interface'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4552262996268248444</id><published>2008-12-11T16:11:00.005Z</published><updated>2008-12-11T16:48:38.021Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><title type='text'>Classloading of GridSphere</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;JSR&lt;/span&gt;-168 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;portlet&lt;/span&gt; applications developed for &lt;a href="http://www.gridsphere.org/download/pub/gridsphere/gridsphere-3.1-src.zip"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;GridSphere&lt;/span&gt; 3.1&lt;/a&gt; has a $CATALINA_HOME/webapps/$PORTLET_WEBAPP/WEB-INF/lib/gridsphere-portletservlet-3.1.jar, which contains a single org.gridsphere.provider.portlet.jsr.PortletServlet class. Originally I thought this class is intended to override the class with the same name in  $CATALINA_HOME/shared/lib, according to the rules of Tomcat class loading, by some "clever" Java programmer. Later I found out this class is exactly the same class as in $CATALINA_HOME/shared/lib.  So though it replaces the one in $CATALINA_HOME/shared/lib, but it changes nothing. In fact, it does change one thing: the defining class loader.&lt;br /&gt;&lt;br /&gt;So if removing $CATALINA_HOME/webapps/$PORTLET_WEBAPP/WEB-INF/lib/gridsphere-portletservlet-3.1.jar, running &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;GridSphere&lt;/span&gt; will raise such an exception:&lt;br /&gt;&lt;br /&gt;16825:ERROR:(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;PortletServlet&lt;/span&gt;.java:&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;loadJSRPortletWebapp&lt;/span&gt;:102)&lt;br /&gt;Unable to create jsr portlet instance: org.gridsphere.gsexamples.portlets.HelloWorld&lt;br /&gt;&lt;br /&gt;java.lang.ClassNotFoundException: org.gridsphere.gsexamples.portlets.HelloWorld&lt;br /&gt;     at java.net.URLClassLoader$1.run(URLClassLoader.java:200)&lt;br /&gt;     at java.security.AccessController.doPrivileged(Native Method)&lt;br /&gt;     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)&lt;br /&gt;     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)&lt;br /&gt;     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)&lt;br /&gt;     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)&lt;br /&gt;     at java.lang.Class.forName0(Native Method)&lt;br /&gt;     at java.lang.Class.forName(Class.java:164)&lt;br /&gt;     at org.gridsphere.provider.portlet.jsr.PortletServlet.loadJSRPortletWebapp(PortletServlet.java:87)&lt;br /&gt;     at org.gridsphere.provider.portlet.jsr.PortletServlet.service(PortletServlet.java:182)&lt;br /&gt;&lt;br /&gt;So basically it complains it can not find the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;portlet&lt;/span&gt; class. Let me explain why.&lt;br /&gt;&lt;br /&gt;First org.gridsphere.provider.portlet.jsr.PortletServlet is defined in the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;portlet&lt;/span&gt; web.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;xml&lt;/span&gt; as the generic &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;servlet&lt;/span&gt;. Not surprisingly, the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;portlet&lt;/span&gt; application is just a web &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;servlet&lt;/span&gt; application in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;GridSphere&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Second, on line 87 of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;PortletServlet&lt;/span&gt;, there is&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;Portlet&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;portletInstance&lt;/span&gt; = (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;Portlet&lt;/span&gt;) Class.forName(portletClass).newInstance();&lt;br /&gt;&lt;br /&gt;It says to use the defining class loader of the current class, i.e., &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;PortletServlet&lt;/span&gt;, to load the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;portlet&lt;/span&gt; class. So if &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;PortletServlet&lt;/span&gt; is inside $CATALINA_HOME/shared/lib, then  there is no way to find the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;portlet&lt;/span&gt; class. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;PortletServlet&lt;/span&gt; has to be put inside $CATALINA_HOME/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;webapps&lt;/span&gt;/$&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;PORTLET&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;WEBAPP&lt;/span&gt;/WEB-INF/lib/.&lt;br /&gt;&lt;br /&gt;I am not very convinced that this is a very elegant solution towards &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;portlet&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;classloading&lt;/span&gt;. Somehow I have a feeling that it might be better if the portal and portlets stay in the same web application, and the webapp classloader acts as the parent of portlet classloaders. Thus, at least, classloading of portlets is not affected by Tomcat classloading rules.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4552262996268248444?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4552262996268248444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4552262996268248444' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4552262996268248444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4552262996268248444'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/classloading-of-gridsphere.html' title='Classloading of GridSphere'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1602220615642220447</id><published>2008-12-10T20:46:00.006Z</published><updated>2008-12-11T16:40:46.093Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='P2P'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>ABC of P2P</title><content type='html'>On 2007, the top two largest P2P networks (protocols) are &lt;a href="http://en.wikipedia.org/wiki/BitTorrent_%28protocol%29"&gt;BitTorrent&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Gnutella"&gt;Gnutella&lt;/a&gt;. BitTorrent was increasing steadily.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://media.arstechnica.com/news.media/p2pshare-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 100%;" src="http://media.arstechnica.com/news.media/p2pshare-2.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The majority of Gnutella users are using &lt;a href="http://en.wikipedia.org/wiki/LimeWire"&gt;LimeWire&lt;/a&gt;. Implemented in Java, LimeWire has a basic version which is open source. It supports BitTorrent as well.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Vuze"&gt;Vuze&lt;/a&gt;, originally named Azureus, is a BitTorrent client. Also implemented in Java, Vuze (Azureus) is &lt;a href="http://sourceforge.net/top/topalltime.php?type=downloads"&gt;the No. 2 most popular download&lt;/a&gt; in SourceForge.&lt;br /&gt;&lt;br /&gt;It is worth mentioning &lt;a href="http://torrentrelay.com/"&gt;TorrentRelay&lt;/a&gt;. It is a purely web-based BitTorrent client. It does not require any software installed on your PC. The BitTorrent downloading is done at the TorrentRelay website. But as a free user, you can not download any file whose size is larger than 800MB.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1602220615642220447?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1602220615642220447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1602220615642220447' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1602220615642220447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1602220615642220447'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/abc-of-p2p.html' title='ABC of P2P'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2973410379303504975</id><published>2008-12-10T15:27:00.002Z</published><updated>2008-12-11T16:40:23.996Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Implement Principles of Modern OS inside Java Application</title><content type='html'>There are some architectural similarities between a modern OS and an OSGi-based Java application.&lt;br /&gt;&lt;br /&gt;For instance, there is a kernel in OS, which provides services to multitasking processes. A shell is there after logging in.&lt;br /&gt;&lt;br /&gt;In an OSGi-based Java application, the OSGi acts as the kernel providing fundamental services to bundles. A shell is there after starting up OSGi. Of course multitasking is available in the form of multithreading.&lt;br /&gt;&lt;br /&gt;In OS, for the safety and security reason, processes are running in their own memory space.&lt;br /&gt;&lt;br /&gt;In OSGi, bundles run in their own code (class) space.&lt;br /&gt;&lt;br /&gt;In OS, &lt;a href="http://en.wikipedia.org/wiki/Selinux"&gt;SELinux&lt;/a&gt; can be used to enforce security policies.&lt;br /&gt;&lt;br /&gt;In Java, &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/SecurityManager.html"&gt;SecurityManager&lt;/a&gt; can be used to enforce security policies.&lt;br /&gt;&lt;br /&gt;It seems to me that as a trend, principles of modern OS are being implemented in complicated, component-based Java software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2973410379303504975?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2973410379303504975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2973410379303504975' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2973410379303504975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2973410379303504975'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/implement-principles-of-modern-os.html' title='Implement Principles of Modern OS inside Java Application'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8375913875584160800</id><published>2008-12-02T14:18:00.008Z</published><updated>2008-12-02T16:05:28.270Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grid Computing'/><title type='text'>Access UK NGS</title><content type='html'>&lt;a href="http://www.grid-support.ac.uk/"&gt;UK NGS&lt;/a&gt; provides national wide grid service. The following is what I have done in order to access NGS facilities.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Apply for a &lt;a href="http://www.grid-support.ac.uk/content/view/23/182/"&gt;UK e-Science certificate&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Apply for an &lt;a href="http://www.grid-support.ac.uk/content/view/221/171/"&gt;NGS account&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Install &lt;a href="http://www.globus.org/toolkit/downloads/4.2.1/"&gt;Globus Toolkit 4.2.1&lt;/a&gt;. &lt;span style="font-weight: bold;"&gt;export $GLOBUS_LOCATION=&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;/usr/local/globus-4.2.1; &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;configure --prefix=$GLOBUS_LOCATION; make; make install &lt;/span&gt;Because my linux box is running RHEL5, I chose to install from source to &lt;a href="http://www.globus.org/toolkit/docs/latest-stable/admin/install/#gtadmin-platform-redhat"&gt;make use of openssl 0.9.8&lt;/a&gt;. Before I installed GT, I also installed a perl-XML-parser which had been missing. The compilation of GT from source took a couple of hours. So be patient.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.grid-support.ac.uk/content/view/217/121/"&gt;Install my UK e-Science certificate&lt;/a&gt;: see the section below the heading "&lt;strong style="font-weight: normal;"&gt;Installing your e-Science Certificate and Private Key&lt;/strong&gt;".&lt;/li&gt;&lt;li&gt;Install UK e-Science CA certificate and signing policy. On &lt;a href="http://www.grid-support.ac.uk/content/view/182/244/"&gt;the NGS CA certificate page&lt;/a&gt;, download CA certificate files &lt;a href="http://ca.grid-support.ac.uk/pub/certs/367b75c3.0"&gt;367b75c3.0&lt;/a&gt; and &lt;a href="http://ca.grid-support.ac.uk/pub/certs/98ef0ee5.0"&gt;98ef0ee5.0&lt;/a&gt;, and signing policy files &lt;span style="font-weight: normal;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.grid-support.ac.uk/files/367b75c3.signing_policy"&gt;367b75c3.signing_policy&lt;/a&gt; and &lt;span style="font-weight: normal;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.grid-support.ac.uk/files/98ef0ee5.signing_policy"&gt;98ef0ee5.signing_policy&lt;/a&gt;. Save them into $HOME/.globus/certificates&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Set up running environment. &lt;span style="font-weight: bold;"&gt;source $GLOBUS_LOCATION/etc/globus-user-env.sh&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a &lt;a href="http://www.globus.org/toolkit/docs/4.0/security/key-index.html#s-security-key-delegation"&gt;proxy certificate&lt;/a&gt;. &lt;span style="font-weight: bold;"&gt;grid-proxy-init -verify -debug &lt;/span&gt;This should not display any error message. To display the current proxy certificate: &lt;span style="font-weight: bold;"&gt;grid-proxy-info&lt;/span&gt;. To destroy the current proxy certificate: &lt;span style="font-weight: bold;"&gt;grid-proxy-destroy&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Use gsissh to connect to NGS nodes. &lt;span style="font-weight: bold;"&gt;gsissh -p 2222 ngs.rl.ac.uk &lt;/span&gt;It uses the proxy certificate, so does not prompt for username and password.&lt;/li&gt;&lt;li&gt;Upload the proxy certificate to the &lt;a href="http://grid.ncsa.uiuc.edu/myproxy/"&gt;MyProxy&lt;/a&gt; server. &lt;span style="font-weight: bold;"&gt;myproxy-init -s myproxy.grid-support.ac.uk -l wjfang&lt;/span&gt; Use "-l" to specify a unique username used in the myproxy server. During the execution, you will be prompted to enter a MyProxy pass phrase. Together with the username, the pass phrase allows to access the proxy certificate stored in the MyProxy server.&lt;/li&gt;&lt;li&gt;Now I can log into &lt;a href="https://portal.ngs.ac.uk/"&gt;NGS Application Repository&lt;/a&gt; even on a different machine using my MyProxy username and pass phrase.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8375913875584160800?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8375913875584160800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8375913875584160800' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8375913875584160800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8375913875584160800'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/12/access-uk-ngs.html' title='Access UK NGS'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5476575931093110618</id><published>2008-11-24T14:32:00.004Z</published><updated>2008-11-25T09:59:29.212Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSGi'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>OSGi: a Dynamic Component System for Java</title><content type='html'>I know &lt;a href="http://www.osgi.org/About/WhatIsOSGi"&gt;OSGi&lt;/a&gt; since I finally adopted &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; as my IDE for Java four years ago.  Recently, two things re-ignite my strong interests in OSGi.&lt;br /&gt;&lt;br /&gt;One is &lt;a href="http://www.gridsphere.org/"&gt;GridSphere&lt;/a&gt;. GridSphere is a portal framework implementing &lt;a href="http://en.wikipedia.org/wiki/JSR-168"&gt;JSR-168&lt;/a&gt;, running on Tomcat. I am evaluating some portlets running in GridSphere. I found out deploying both GridSphere and portlets in GridSphere need to restart the JVM. It is clear to me this is not a desirable feature that an enterprise software should have. The selling point of the portal framework is that the portlets (i.e., the components) can be developed asynchronously and distributed, while can work in harmony in a portal. Let's say we have a portal that contains 25 portlets. Each portlet each year releases two major updates and two security patches. If we need to restart the portal every time when we update a portlet, then we need to restart the portal 100 times every year. This is not a good news to the administrator. Clearly we should have better support for components in architecting server-side software. At least, we should allow individual component be deployed and undeployed dynamically without affecting the remaining part of the system. By the way, 10 years ago in an interview with &lt;a href="http://www.huawei.com/"&gt;Huawei&lt;/a&gt;, I was asked the question how to patch a software when it is still running.&lt;br /&gt;&lt;br /&gt;The other is &lt;a href="http://www.springsource.com/products/suite/dmserver"&gt;SpringSource dm server&lt;/a&gt;,  which uses OSGi. It seems to me OSGi is the answer to the architectural challenges in any complex, server-side, enterprise, or component-based software.&lt;br /&gt;&lt;br /&gt;A further look at the OSGi website reveals that OSGi is behind many web application servers and J2EE servers: IBM Websphere, SpringSource Application Server, Oracle (formerly BEA) Weblogic, Sun's GlassFish, and Redhat's JBoss. And not surprisingly, the top two showcases for adopting OGSi are Eclipse and Spring.&lt;br /&gt;&lt;br /&gt;Adopting OSGi is claimed to have &lt;a href="http://www.osgi.org/About/WhyOSGi"&gt;many benefits&lt;/a&gt;, including dynamic update of bundle, security, support for dependencies and versioning, simple API and small footprint. To achieve those, OSGi has the module and service concepts deep in design.&lt;br /&gt;&lt;br /&gt;In OSGi, the sharing between modules, like importing jars from other modules and exporting own jars for other modules to use, must be declared explicitly. By default, nothing is shared.&lt;br /&gt;&lt;br /&gt;There is a service registry in OSGi. A service can be implemented using any POJO. While the OSGi Alliance publishes the Compendium specifications, which define a large number of standard services, from a Log Service to a Measurement and State specification.&lt;br /&gt;&lt;br /&gt;In terms of the implementation, the two most popular ones are &lt;a href="http://felix.apache.org/site/index.html"&gt;Apache Felix&lt;/a&gt; and &lt;a href="http://www.eclipse.org/equinox/"&gt;Eclipse Equinox&lt;/a&gt;. My next step would be doing some hands on exercise with either of them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5476575931093110618?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5476575931093110618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5476575931093110618' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5476575931093110618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5476575931093110618'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/osgi-dynamic-component-system-for-java.html' title='OSGi: a Dynamic Component System for Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1300882003488621254</id><published>2008-11-21T14:24:00.009Z</published><updated>2008-11-21T15:56:22.170Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Tweak the Delegation Model of Java Class Loading</title><content type='html'>&lt;span style="font-family:Verdana,Arial,Helvetica;"&gt;&lt;a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html"&gt;The Java class loader architecture&lt;/a&gt; [&lt;a href="http://www.developer.com/java/other/article.php/10936_2248831_1"&gt;1&lt;/a&gt;, &lt;a href="http://www.developer.com/java/other/article.php/10936_2248831_2"&gt;2&lt;/a&gt;] affords a Java developer a tremendous amount of flexibility in the way that an application is assembled and  extended. Basically, class loaders form a hierarchy where the root is &lt;/span&gt; &lt;span style="font-family:Verdana,Arial,Helvetica;"&gt;&lt;span style="font-style: italic;"&gt;bootstrap&lt;/span&gt;, who is the parent of sun.misc.Launcher$ExtClassLoader, who is the parent of sun.misc.Launcher$AppClassLoader. When a class loader is asked to load a class, it will first delegate the request to its parent. This is why it is called the delegation model.&lt;br /&gt;&lt;br /&gt;But, occalsionally, we do need to tweek this delegation model in some way that is more suitable to our requirement. A good example is in the implementation of &lt;a href="http://en.wikipedia.org/wiki/Servlet"&gt;Java Servlet Specification&lt;/a&gt;. For instance, in Tomcat 6, the web application class loader attempts to load its classes before delegate the request to its parent, the &lt;span style="font-style: italic;"&gt;common &lt;/span&gt;class loader.&lt;br /&gt;&lt;br /&gt;The delegation model is implemented in java.lang.ClassLoader's protected method loadClass(String name, boolean resolve):&lt;pre&gt;protected synchronized Class loadClass(String name,&lt;br /&gt;boolean resolve) throws ClassNotFoundException {&lt;br /&gt;// First, check if the class has already been loaded&lt;br /&gt;Class c = findLoadedClass(name);&lt;br /&gt;if (c == null) {&lt;br /&gt;   try {&lt;br /&gt;   if (parent != null) {&lt;br /&gt;       c = parent.loadClass(name, false);&lt;br /&gt;   } else {&lt;br /&gt;       c = findBootstrapClass0(name);&lt;br /&gt;   }&lt;br /&gt;   } catch (ClassNotFoundException e) {&lt;br /&gt;       // If still not found, then invoke findClass&lt;br /&gt;       // in order to find the class.&lt;br /&gt;       c = findClass(name);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;if (resolve) {&lt;br /&gt;   resolveClass(c);&lt;br /&gt;}&lt;br /&gt;return c;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The following program shows how to override the protected method loadClass to tweak the delegation model. In the program, the classes inside the package "somewhere" will be loaded from somewhere else even the classes with the same name exist in the application classpath. For loading all the other classes, the delegation model is still respected.&lt;br /&gt;&lt;pre&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.FileNotFoundException;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;&lt;br /&gt;import somewhere.Greet;&lt;br /&gt;&lt;br /&gt;public class ClassLoaderTest {&lt;br /&gt;public static class MyClassLoader extends ClassLoader {&lt;br /&gt;@Override&lt;br /&gt;protected synchronized Class loadClass(&lt;br /&gt;String name, boolean resolve)&lt;br /&gt;throws ClassNotFoundException {&lt;br /&gt;  Class c = findLoadedClass(name);&lt;br /&gt;  if (c == null) {&lt;br /&gt;    if (name != null &amp;amp;&amp;amp; name.startsWith("somewhere."))&lt;br /&gt;      c = findClass(name);&lt;br /&gt;    else&lt;br /&gt;      c = this.getParent().loadClass(name);&lt;br /&gt;  }&lt;br /&gt;  if (resolve) {&lt;br /&gt;    resolveClass(c);&lt;br /&gt;  }&lt;br /&gt;  return c;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;protected Class findClass(String name)&lt;br /&gt;throws ClassNotFoundException {&lt;br /&gt;byte[] buf = loadFromSomewhere(name);&lt;br /&gt;return defineClass(name, buf, 0, buf.length);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private byte[] loadFromSomewhere(String name)&lt;br /&gt;throws ClassNotFoundException {&lt;br /&gt;String className = name.substring("somewhere.".length());&lt;br /&gt;FileInputStream fis = null;&lt;br /&gt;try {&lt;br /&gt;fis = new FileInputStream("./class/somewhere/" + className&lt;br /&gt;  + ".class");&lt;br /&gt;} catch (FileNotFoundException e) {&lt;br /&gt;throw new ClassNotFoundException(e.getMessage());&lt;br /&gt;}&lt;br /&gt;byte[] buffer = new byte[8192];&lt;br /&gt;int n = 0;&lt;br /&gt;try {&lt;br /&gt;int c = fis.read(buffer);&lt;br /&gt;n = c;&lt;br /&gt;while (c != -1) {&lt;br /&gt; c = fis.read(buffer, n, buffer.length - n);&lt;br /&gt; n += c;&lt;br /&gt;}&lt;br /&gt;fis.close();&lt;br /&gt;n++;&lt;br /&gt;} catch (IOException e) {&lt;br /&gt;throw new ClassNotFoundException(e.getMessage());&lt;br /&gt;}&lt;br /&gt;byte[] rv = new byte[n];&lt;br /&gt;System.arraycopy(buffer, 0, rv, 0, n);&lt;br /&gt;return rv;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* @param args&lt;br /&gt;* @throws ClassNotFoundException&lt;br /&gt;*/&lt;br /&gt;public static void main(String[] args) throws Exception {&lt;br /&gt;MyClassLoader myClassLoader = new MyClassLoader();&lt;br /&gt;Class clazz = myClassLoader.loadClass("somewhere.Greet");&lt;br /&gt;Object object = clazz.newInstance();&lt;br /&gt;Method method = clazz.getMethod("hello");&lt;br /&gt;// Greet from somewhere, print out "hello world"&lt;br /&gt;method.invoke(object);&lt;br /&gt;&lt;br /&gt;Greet greet = new Greet();&lt;br /&gt;// local Greet, print out "good morning"&lt;br /&gt;greet.hello();&lt;br /&gt;// java.lang.ClassCastException:&lt;br /&gt;// somewhere.Greet cannot be cast to somewhere.Greet&lt;br /&gt;greet = (Greet) object;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In fact, A loaded class in a JVM is identified by its fully qualified name and its defining class loader. Consequently, each class loader in the JVM can be said to define its own namespace.&lt;br /&gt;&lt;br /&gt;Therefore, leveraging the Java class loader architecture, components inside a Java process are able to have their own, separated code (class) space. This partly forms the foundation for that individual component can be plugged and played as well as hot swapped without affecting the other components in the same process.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1300882003488621254?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1300882003488621254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1300882003488621254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1300882003488621254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1300882003488621254'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/tweak-delegation-model-of-java-class.html' title='Tweak the Delegation Model of Java Class Loading'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3611161373257037233</id><published>2008-11-19T17:01:00.009Z</published><updated>2008-11-19T17:28:01.450Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Let Java SSL Trust All Certificates without Violating Security Manager</title><content type='html'>Java SSL by default does not trust self-signed certificate. &lt;a href="http://en.wikibooks.org/wiki/Programming:WebObjects/Web_Services/How_to_Trust_Any_SSL_Certificate"&gt;Wikibooks:Programming&lt;/a&gt; reveals a way to allow connection to secure HTTP server using self-signed certificate. The magic looks like:&lt;br /&gt;&lt;br /&gt;       // Create a trust manager that does not validate certificate chains&lt;br /&gt;       TrustManager[] trustAllCerts = new TrustManager[]{&lt;br /&gt;           new X509TrustManager() {&lt;br /&gt;               public java.security.cert.X509Certificate[] getAcceptedIssuers() {&lt;br /&gt;                   return null;&lt;br /&gt;               }&lt;br /&gt;            &lt;br /&gt;               public void checkClientTrusted(&lt;br /&gt;                       java.security.cert.X509Certificate[] certs, String authType) {&lt;br /&gt;                   // do nothing&lt;br /&gt;               }&lt;br /&gt;            &lt;br /&gt;               public void checkServerTrusted(&lt;br /&gt;                       java.security.cert.X509Certificate[] certs, String authType) {&lt;br /&gt;                   // do nothing&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       };&lt;br /&gt;    &lt;br /&gt;       // Install the all-trusting trust manager&lt;br /&gt;       SSLContext sc = null;&lt;br /&gt;       try {&lt;br /&gt;           sc = SSLContext.getInstance("SSL");&lt;br /&gt;           sc.init(null, trustAllCerts, new java.security.SecureRandom());&lt;br /&gt;       } catch(GeneralSecurityException gse) {&lt;br /&gt;               throw new IllegalStateException(gse.getMessage());&lt;br /&gt;       }&lt;br /&gt;       HttpsURLConnection.setDefaultSSLSocketFactory(&lt;br /&gt;sc.getSocketFactory());&lt;br /&gt;&lt;br /&gt;However, HttpsURLConnection.setDefaultSSLSocketFactory(...) will throw a SecurityException (a RuntimeException) if a security manager exists and its checkSetFactory method does not allow a socket factory to be specified. The thrown SecurityException looks like&lt;br /&gt;&lt;br /&gt;Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission setFactory)&lt;br /&gt;at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)&lt;br /&gt;at java.security.AccessController.checkPermission(AccessController.java:546)&lt;br /&gt;at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)&lt;br /&gt;at java.lang.SecurityManager.checkSetFactory(SecurityManager.java:1612)&lt;br /&gt;at javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(HttpsURLConnection.java:308)&lt;br /&gt;at SecurityManagerTest.main(SecurityManagerTest.java:50)&lt;br /&gt;&lt;br /&gt;A workaround to avoid such a SecurityException is as below:&lt;br /&gt;&lt;br /&gt;URL url = new URL("https://engage.ac.uk");&lt;br /&gt;HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();&lt;br /&gt;conn.setSSLSocketFactory(sc.getSocketFactory());&lt;br /&gt;conn.getInputStream();&lt;br /&gt;&lt;br /&gt;The trick is to use the instance method setSSLSocketFactory instead of the static method setDefaultSSLSocketFactory. The former does not throw a SecurityException.&lt;br /&gt;&lt;br /&gt;Note: need to use conn.getInputStream() instead of url.openStream(), otherwise the customised SocketFactory won't be used.&lt;br /&gt;&lt;br /&gt;Of course to allow to connect the secure web site, the following permission should be added in the Java security policy file:&lt;br /&gt;&lt;br /&gt;permission java.net.SocketPermission "engage.ac.uk:443", "connect";&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3611161373257037233?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3611161373257037233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3611161373257037233' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3611161373257037233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3611161373257037233'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/let-java-ssl-trust-all-certificates.html' title='Let Java SSL Trust All Certificates without Violating Security Manager'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8353761943310625677</id><published>2008-11-19T15:19:00.009Z</published><updated>2008-11-19T16:25:04.017Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><title type='text'>Use Security Manager to Control Java Web Application Behavior</title><content type='html'>In a Java web application server like Tomcat, we have the Tomcat container and multiple web applications running in the same JVM. It is thus very important to cut the unexpected interactions between applications and between applications and Tomcat. Ideally it is expected the behavior of one web application should not affect the behavior of other applications as well as Tomcat, in a bad way.&lt;br /&gt;&lt;br /&gt;One of such unexpected interactions is caused by modifying shared classes and objects, for instance, changing system properties, changing system classes' behavior.&lt;a href="http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html"&gt;&lt;br /&gt;&lt;br /&gt;Tomcat 5.5's class loaders&lt;/a&gt; are organised as:&lt;br /&gt;&lt;pre&gt;      Bootstrap&lt;br /&gt;  |&lt;br /&gt;System&lt;br /&gt;  |&lt;br /&gt;Common&lt;br /&gt;/      \&lt;br /&gt;Catalina   Shared&lt;br /&gt;     /   \&lt;br /&gt;Webapp1  Webapp2 ...&lt;br /&gt;&lt;/pre&gt;&lt;a href="http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html"&gt;Tomcat 6.0's class loaders&lt;/a&gt; are organised as:&lt;br /&gt;&lt;pre&gt;      Bootstrap&lt;br /&gt;   |&lt;br /&gt;System&lt;br /&gt;   |&lt;br /&gt;Common&lt;br /&gt;/     \&lt;br /&gt;Webapp1   Webapp2 ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In both cases, web applications and Tomcat share the classes managed by class loaders Bootstrap, System and Common.&lt;br /&gt;&lt;br /&gt;Let's say one web application use the following code to tell Java runtime to use the XSLT implementation shipped with JDK.&lt;br /&gt;&lt;br /&gt;System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");&lt;br /&gt;&lt;br /&gt;Other web applications may choose to use other XSLT implementations in a similar way. If a certain web application's correct behavior is depending on a particular XLST implementation, then we may get a problem, because System.setProperty("javax.xml.transform.TransformerFactory", ...) will change the JVM-wide XSLT implementation.&lt;br /&gt;&lt;br /&gt;Therefore it is advisable to &lt;a href="http://tomcat.apache.org/tomcat-6.0-doc/security-manager-howto.html"&gt;use Java security manager to control the permissions granted to web application code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note $CATALINA_HOME/bin/startup.sh does not start up a Tomcat with the security manager. To enable the security manager, use $CATALINA_HOME/bin/startup.sh -security. It will append "-Djava.security.manager -Djava.security.policy=..." to the JVM arguments.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A simple Java program testing security manager and policy file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;public class SecurityManagerTest {&lt;br /&gt;public static void main(String[] args) throws Exception {&lt;br /&gt;   System.setProperty("greeting", "hello world!");&lt;br /&gt;   System.out.println(System.getProperty("greeting"));&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Run this program, you will see "hello world!" printed out.&lt;br /&gt;&lt;br /&gt;Prepare a policy file called lab.policy:&lt;br /&gt;&lt;br /&gt;grant {&lt;br /&gt;    permission java.util.PropertyPermission "*", "read";&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;It says any code can only read system properties, but not write.&lt;br /&gt;&lt;br /&gt;By the way, the policy file can be created using &lt;a href="http://java.sun.com/javase/6/docs/technotes/tools/index.html#security"&gt;policytool&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then run the program like this:&lt;br /&gt;&lt;br /&gt;java -Djava.security.manager -Djava.security.policy=lab.policy SecurityManagerTest&lt;br /&gt;&lt;br /&gt;You will see an excpetion pop up:&lt;br /&gt;&lt;br /&gt;Exception in thread "main" java.security.AccessControlException: access denied (java.util.PropertyPermission greeting write)&lt;br /&gt;at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)&lt;br /&gt;at java.security.AccessController.checkPermission(AccessController.java:546)&lt;br /&gt;at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)&lt;br /&gt;at java.lang.System.setProperty(System.java:727)&lt;br /&gt;at SecurityManagerTest.main(SecurityManagerTest.java:11)&lt;br /&gt;&lt;br /&gt;See the security manager is working. It is important to give the right location for the policy file. Because when the security manager is enabled, by default no permission is granted. So any permission will be denied except those defined in the policy file. In case the policy file cannot be found, then the code is given no permission at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8353761943310625677?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8353761943310625677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8353761943310625677' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8353761943310625677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8353761943310625677'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/use-security-manager-to-control-java.html' title='Use Security Manager to Control Java Web Application Behavior'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8527169772275237838</id><published>2008-11-14T16:34:00.002Z</published><updated>2008-11-14T16:44:49.169Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='RHEL'/><title type='text'>Update RHEL5</title><content type='html'>See &lt;a href="https://secure.ecs.soton.ac.uk/kb/entry/84/"&gt;here&lt;/a&gt; (within intranet, may require authentication)  for how to register RHEL4 for up2date and RHEL5 for yum.&lt;br /&gt;&lt;br /&gt;After that, then can use &lt;span style="font-weight: bold;"&gt;yum update&lt;/span&gt; for a complete update.&lt;br /&gt;&lt;br /&gt;To install a certain package: &lt;span style="font-weight: bold;"&gt;yum install package_name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To see what a package does: &lt;span style="font-weight: bold;"&gt;yum provides package_name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To find packages containing some keyword: &lt;span style="font-weight: bold;"&gt;yum list | grep keyword&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To check already installed packages that contains some keyword: &lt;span style="font-weight: bold;"&gt;rpm -qa | grep keyword&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8527169772275237838?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8527169772275237838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8527169772275237838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8527169772275237838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8527169772275237838'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/update-rhel5.html' title='Update RHEL5'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3496525365030909607</id><published>2008-11-11T22:19:00.007Z</published><updated>2008-11-18T11:19:21.843Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JeOS'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Machine'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Make a Java-enabled Virtual Machine Using Ubuntu JeOS</title><content type='html'>As suggested in &lt;a href="http://www.vmware.com/appliances/build/best_practices.html"&gt;the best practice&lt;/a&gt; to build a &lt;a href="http://en.wikipedia.org/wiki/Virtual_appliance"&gt;virtual appliance&lt;/a&gt; by VMware, &lt;a href="http://www.ubuntu.com/products/whatisubuntu/serveredition/jeos"&gt;Ubuntu JeOS&lt;/a&gt; is used as the operating system. In around 100MB, it provides a &lt;a href="http://en.wikipedia.org/wiki/Jeos"&gt;just enough OS&lt;/a&gt;. After installed, its VMware virtual disk file size is about 380MB.&lt;br /&gt;&lt;br /&gt;By default, Ubuntu does not provide a root password. The root privilege is carried out using the "sudo" command. To enable root login: &lt;span style="font-weight: bold;"&gt;sudo passwd root&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Also, see &lt;a href="https://help.ubuntu.com/community/JeOS"&gt;how to prepare a virtual appliance&lt;/a&gt; from the Ubuntu community.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Adding a new virtual disk&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;To add a new virtual disk, using the "Add Hardware" command in VMware web interface. &lt;/li&gt;&lt;li&gt;Need to restart the virtual machine to detect the new virtual disk. &lt;/li&gt;&lt;li&gt;Let's say the newly added hard drive is /dev/sdb. Use the following command to partition it: &lt;span style="font-weight: bold;"&gt;fdisk /dev/sdb&lt;/span&gt;. To create a single new partition, the entire size of /dev/sdb: n ENTER p ENTER 1 ENTER (default) ENTER (default) ENTER w ENTER.&lt;/li&gt;&lt;li&gt;To format it: &lt;span style="font-weight: bold;"&gt;mkfs.ext3 /dev/sdb&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;To mount it on an existing location, say /data: &lt;span style="font-weight: bold;"&gt;mount /dev/sdb /data&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;See &lt;a href="http://ubuntuforums.org/showthread.php?t=267869"&gt;how to format a new hard disk&lt;/a&gt; on ubuntu forums.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Making a Java appliance&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The next step will be to make it a Java appliance, with JDK, ant as well as Tomcat installed, running some Java application like Grimoires.&lt;br /&gt;&lt;br /&gt;Ubuntu JeOS does not pre-install Open SSH server. Use the following command to install Open SSH:&lt;span style="font-weight: bold;"&gt; apt-get install openssh-server&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Then install&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JDK 1.6.0_10&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Apache Ant 1.7.1&lt;/li&gt;&lt;li&gt;Apache Tomcat 5.5.27&lt;/li&gt;&lt;li&gt;Grimoires 2.0.0&lt;/li&gt;&lt;/ul&gt;The used disk space shown by "df" inside virtual machine is about 675MB.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Setting up NAT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Assume the virtual machine has been configured to support NAT. Add the following line to /etc/vmware/vmnet8/nat/nat.conf, under the [incomingtcp] section:&lt;br /&gt;&lt;br /&gt;6660 = 172.16.59.132:8080&lt;br /&gt;&lt;br /&gt;where 172.16.59.132 is the IP address of the virtual machine.&lt;br /&gt;&lt;br /&gt;According to the VMware server user guide, clicking "Refresh Network List" in the Virtual Infrastructure web interface should bring up the modified network configuration. But it does not work in my case. I have to restart VMware to enforce the new NAT configuration: &lt;span style="font-weight: bold;"&gt;service vmware restart&lt;/span&gt;. (Better shut down vm before restart vmware server!)&lt;br /&gt;&lt;br /&gt;After restart VMware, and make sure the port 6660 is opened in the firewall of the host machine, access http://hostname_of_the_host:6660/grimoires from another machine.&lt;br /&gt;&lt;br /&gt;It seems that vmware server runs a separate daemon to handle the address translation when vm is set to use NAT.  So this blocks &lt;a href="http://www.linuxtopia.org/online_books/rhel5/rhel5_administration/rhel5_ch-iptables.html"&gt;iptables&lt;/a&gt;' &lt;a href="http://www.linuxtopia.org/online_books/rhel5/rhel5_administration/rhel5_ch-fw.html#s1-firewall-ipt-fwd"&gt;NAT configuration&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cloning the Virtual Machine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is something a little bit tricky.&lt;br /&gt;&lt;br /&gt;I used the conventional way to clone it: copy the vmdk and vmx files; then add the clone virtual machine to the inventory ("Add Virtual Machine to Inventory"); when asked whether you copied it or moved it, answer copied it.&lt;br /&gt;&lt;br /&gt;The clone was able to start up. But there was no eth0. The routing table was empty (shown by&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;route&lt;/span&gt;). There was an eth1 with the correct MAC address but without IP information (shown by &lt;span style="font-weight: bold;"&gt;ifconfig&lt;/span&gt;). Not surprisingly, TCP/IP was not working.&lt;br /&gt;&lt;br /&gt;My judgement was that there was no reason for the virtual network card to go wrong, so it should be due to some configuration issue.&lt;br /&gt;&lt;br /&gt;Hinted by a post about adding a second network card to Ubuntu, I used &lt;span style="font-weight: bold;"&gt;dmesg | grep eth&lt;/span&gt; to check the kernel messages on booting. Then I found an interesting message: "udev: rename eth0 to eth1".  After a little bit googling and investigation, I solved the problem!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Udev"&gt;udev&lt;/a&gt; is the device manager for the Linux 2.6 kernel series. In /etc/udev/rules.d/70-persistent-net.rules, there were two lines:&lt;br /&gt;SUBSYSTEM=="net", ...... ATTR{address}=="00:0c:29:07:6f:37", ...... NAME="eth0"&lt;br /&gt;SUBSYSTEM=="net", ...... ATTR{address}=="00:0c:29:cf:c8:64", ...... NAME="eth1"&lt;br /&gt;&lt;br /&gt;The MAC address in the first line is the one of the original vm, while the  MAC address in the second line is the correct MAC address of the clone. Clearly, the first line has no effect, because there is no such a device in the system. And the second line adds the network card as eth1.&lt;br /&gt;&lt;br /&gt;Looking at /etc/network/interfaces, it only defines lo and eth0. eth0 is defined like this:&lt;br /&gt;auto eth0&lt;br /&gt;iface eth0 inet dhcp&lt;br /&gt;&lt;br /&gt;There is no wonder why only eth1 was visible but did not support TCP/IP. After commenting out the first line and changing eth1 to eth0 in the second line in  /etc/udev/rules.d/70-persistent-net.rules, and restarting the system, TCP/IP is working!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a convenient way to prepare a small footprint Virtual Machine for running Java. It can be used to deliver Java software, or as a test or evaluation environment for Java product.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3496525365030909607?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3496525365030909607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3496525365030909607' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3496525365030909607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3496525365030909607'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/ubuntu-jeos.html' title='Make a Java-enabled Virtual Machine Using Ubuntu JeOS'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1655349688657010376</id><published>2008-11-06T22:00:00.003Z</published><updated>2008-12-02T09:33:09.881Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><title type='text'>OpenSSL</title><content type='html'>Recently I used the &lt;a href="http://www.openssl.org/"&gt;openssl&lt;/a&gt; utility to generate key pairs and certificates. For example,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;To generate a private key: openssl genrsa -out ca.key 2048&lt;/li&gt;&lt;li&gt;To create a self-signed certificate: openssl req -new -key ca.key -x509 -days 365 -out ca.crt&lt;br /&gt;&lt;/li&gt;&lt;li&gt;To create a certificate signing request: openssl req -new -key temp.key -out temp.csr&lt;/li&gt;&lt;li&gt;To create a certificate from a certificate signing request: openssl x509 -req -in temp.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out temp.crt&lt;/li&gt;&lt;li&gt;To display a certificate: openssl x509 -text -in temp.crt&lt;/li&gt;&lt;li&gt;To display the content of a pkcs12 formatted certificate (the displayed private key and certificate are in PEM format, which can be used in the above commands): openssl pkcs12 -in old_uk_escience.p12 -out old.txt&lt;/li&gt;&lt;li&gt;To convert from pkcs12 format to PEM format: openssl pkcs12 -in cred.p12 -out cert.pem -nodes -clcerts -nokeys, openssl pkcs12 -in cred.p12 -out key.pem -nodes -nocerts&lt;br /&gt;&lt;/li&gt;&lt;li&gt;To create pkcs12 format certificate using PEM format private key and certificate: openssl pkcs12 -in temp.crt -inkey temp.key -out temp.p12 -export&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1655349688657010376?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1655349688657010376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1655349688657010376' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1655349688657010376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1655349688657010376'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/openssl.html' title='OpenSSL'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3751621002450746694</id><published>2008-11-06T15:04:00.005Z</published><updated>2008-11-06T22:22:31.469Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cryptography'/><title type='text'>Self-Decrypting HTML Page</title><content type='html'>This is something worthy doing. Let's call it self-decrypting HTML page.&lt;br /&gt;&lt;br /&gt;It is a publicly accessible, encrypted HTML page, that can be hosted in any website, but can only be decrypted by authorized persons who know the key. JavaScript can be used to perform encryption and decryption locally at the browser. Thus what is transmitted on the net and stays at the public website is the encrypted information, which guarantees the confidentiality of the information.&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;/span&gt;Some &lt;a href="http://en.wikipedia.org/wiki/Symmetric_key_algorithm"&gt;symmetric key algorithm&lt;/a&gt; is preferred.&lt;br /&gt;&lt;br /&gt;A self-decrypting HTML page generator is needed to convert the to-be-protected information to a self-decrypting HTML page.&lt;br /&gt;&lt;br /&gt;It is noted that a United States Patent &lt;a href="http://www.freepatentsonline.com/7003800.html"&gt;7003800&lt;/a&gt; has been filed on "Self-decrypting web site pages". It seems it talks about a method pertinent to a web site.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://leemon.com/crypto/SelfDecrypt.html"&gt;self-decrypting email utility&lt;/a&gt; performs the similar task, which uses &lt;a href="http://en.wikipedia.org/wiki/Rc4"&gt;RC4&lt;/a&gt; as the cipher. Here is the &lt;a href="http://farhadi.ir/works/rc4"&gt;JavaScript code&lt;/a&gt; for RC4.&lt;br /&gt;&lt;br /&gt;Compared with another web-based confidential information system, i.e., some information is hosted on a HTTPS server and is protected by some authentication method, self-decrypting HTML page does not require an authentication method, thus no need for user management. All needed to access the confidential information is the URL of the self-decrypting HTML page and the key.&lt;br /&gt;&lt;br /&gt;Will &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; be a good platform for this? Will it be possible to use &lt;a href="https://www.google.com/adsense/"&gt;Google AdSense&lt;/a&gt; to generate revenue from this application?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3751621002450746694?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3751621002450746694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3751621002450746694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3751621002450746694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3751621002450746694'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/self-decrypting-html-page.html' title='Self-Decrypting HTML Page'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1154946363542266057</id><published>2008-11-04T14:40:00.003Z</published><updated>2008-11-04T15:29:59.276Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Handle Chinese in Java</title><content type='html'>(This is one of my old Google Notes.)&lt;br /&gt;&lt;br /&gt;In Java, &lt;span style="font-style: italic;"&gt;Reader&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;Writer&lt;/span&gt; are used to handle character (&lt;span style="font-style: italic;"&gt;char&lt;/span&gt;) stream, and &lt;span style="font-style: italic;"&gt;InputStream &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;OutputStream&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;/span&gt;are used to&lt;span style="font-style: italic;"&gt; &lt;/span&gt;handle &lt;span style="font-style: italic;"&gt;byte &lt;/span&gt;streams. &lt;span style="font-style: italic;"&gt;InputStreamReader &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;OutuptStreamWriter &lt;/span&gt;are bridges between byte streams and character streams.&lt;br /&gt;&lt;br /&gt;Characters can have many different coding schemes, such as ASCII, GB2312, UTF-8 (Unicode Transformation Format), when they are represented in bytes. While characters in Java, char or String, are &lt;span style="font-style: italic;"&gt;Unicode &lt;/span&gt;only.&lt;br /&gt;&lt;br /&gt;A &lt;span style="font-style: italic;"&gt;Charset &lt;/span&gt;is a named mapping between sequences of sixteen-bit Unicode, which is the character representation in Java, and sequences of bytes. A Charset knows how to convert a byte sequence to a (Unicode) char sequence, and vice versa, following the standard it implements.&lt;br /&gt;&lt;br /&gt;Not surprisingly, both InputStreamReader and OutuptStreamWriter can be configured to use a specified Charset,  but there is no concept of Charset in Reader and Writer.&lt;br /&gt;&lt;br /&gt;The following Java program demonstrates how to handle Chinese in Java.&lt;br /&gt;&lt;br /&gt;import java.io.BufferedWriter;&lt;br /&gt;import java.io.OutputStreamWriter;&lt;br /&gt;&lt;br /&gt;public class ChineseTest {&lt;br /&gt;   public static void main(String[] args) throws Exception {&lt;br /&gt;       String chinese = "\u4eca\u65e5\u83dc\u6839\u8c2d"; // 1&lt;br /&gt;       System.out.println(chinese);  //2&lt;br /&gt;       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out, "GB2312")); //3&lt;br /&gt;       bw.write(chinese); //4&lt;br /&gt;       bw.close(); //5&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Code comments:&lt;br /&gt;&lt;ol&gt;&lt;li style="font-family: arial;"&gt;This is the Unicode for 今日菜根谭, generated by "native2ascii -encoding GB2312 c.txt", where the content of c.txt is 今日菜根谭 encoded in GB2312. The utility native2ascii converts a file with native-encoded characters (characters which are non-Latin 1 and non-Unicode) to one with Unicode-encoded characters.&lt;br /&gt;&lt;/li&gt;&lt;li style="font-family: arial;"&gt;Can't print 今日菜根谭, by using the platform's default Charset.&lt;/li&gt;&lt;li style="font-family: arial;"&gt;Create a Writer using the GB2312 Charset.&lt;/li&gt;&lt;li style="font-family: arial;"&gt;Now we can print out 今日菜根谭.&lt;/li&gt;&lt;li style="font-family: arial;"&gt;Flush the output. Required.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1154946363542266057?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1154946363542266057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1154946363542266057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1154946363542266057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1154946363542266057'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/handle-chinese-in-java.html' title='Handle Chinese in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5311228154676844350</id><published>2008-11-04T14:09:00.001Z</published><updated>2008-11-04T14:24:56.877Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Virtual DOM</title><content type='html'>(This is one of my old Google Notes. Virtual DOM is a small piece of software I implemented.)&lt;br /&gt;&lt;br /&gt;Complying with the W3C DOM interface, Virtual DOM is capable of representing in memory a large XML data which can not be represented using other DOM implementations such as Xerces. Virtual DOM is aiming at allowing off-the-shelf XPath engines such as Jaxen to process XML DOM representation that is too large to be held in memory otherwise. To support such a goal, Virtual DOM must be told how to load DOM element, and then it uses SoftReference to cache the loaded element. To put it in a simple way, the Virtual DOM elements can be garbage collected when Java heap space becomes scarce, and later be reloaded on demand.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The problem of Xerces DOM implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Each node has references to its parent, children, and siblings. So as long as there is a single reference to any node of the DOM tree, any parts of the tree can not be garbage collected.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Implementation of Virtual DOM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Virtual DOM adopts a forest mode, where there is a virtual document and a virtual root element. The virtual root element has a number of child elements, which is implemented as CollectableElement extended from CollectableNode, each representing a different DOM document.&lt;br /&gt;&lt;br /&gt;Each Virtual DOM node, called CollectableNode, has a reference to DocumentCache, which in turn has a SoftReference to the cached owning document. DocumentCache also has enough information to load and reload the owning document whenever necessary.&lt;br /&gt;&lt;br /&gt;Each Virtual DOM node has information specifying how to locate this node from the root node of the owning document.&lt;br /&gt;&lt;br /&gt;Each Virtual DOM node also has a SoftReference to its corresponding concrete DOM node for convenience purpose.&lt;br /&gt;&lt;br /&gt;The CollectableElement that is the direct child of the virtual root element has an index indicating which child it is in terms of the virtual root element. Thus it is able to retrieve its next sibling.&lt;br /&gt;&lt;br /&gt;All exported DOM references should be of Collectable* instead of the default DOM ones to prevent DOM node references from being held externally.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Test&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With 64 MB heap, using a revised Jaxen 1.1 (one of Jaxen 1.1's methods unnecessarily retains object references.), Virtual DOM is able to deal with at least 250,000 instances of a certain XML document. In a comparison, Xerces DOM runs out of memory at 39,000 instances.&lt;br /&gt;&lt;br /&gt;(It is called VirtualDOM in my Eclipse projects.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5311228154676844350?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5311228154676844350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5311228154676844350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5311228154676844350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5311228154676844350'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/virtual-dom.html' title='Virtual DOM'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-9000659721761522061</id><published>2008-11-04T12:00:00.002Z</published><updated>2008-11-04T12:18:49.505Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSPWiki'/><title type='text'>JSPWiki ACL Filter</title><content type='html'>&lt;p&gt;I am working on &lt;a href="http://www.omii.ac.uk"&gt;the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;OMII&lt;/span&gt;-UK website&lt;/a&gt;. &lt;a href="http://www.jspwiki.org"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;JSPWiki&lt;/span&gt;&lt;/a&gt; has been adopted as the &lt;a href="http://en.wikipedia.org/wiki/Web_content_management_system"&gt;web content management system&lt;/a&gt; as well as a wiki in the website. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;JSPWiki&lt;/span&gt; has been customised with an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;OMII&lt;/span&gt;-UK template, and authentication and authorization &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;modules&lt;/span&gt;. There are many users, so &lt;a class="external" href="http://doc.jspwiki.org/2.4/wiki/Security#section-Security-AccessControlLists" rel="nofollow"&gt;In-page &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;ACLs&lt;/span&gt;&lt;/a&gt; are adopted to protect some page from unauthorised editing. For instance, the following &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ACLs&lt;/span&gt; say only members of staff group can view and edit the page containing this &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;ACL&lt;/span&gt;: &lt;/p&gt; &lt;pre&gt;&lt;span style="font-family: arial;"&gt;[{ALLOW edit &lt;/span&gt;&lt;span style="font-family: arial;" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;StaffGroup&lt;/span&gt;&lt;span style="font-family: arial;"&gt;}]&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt; &lt;p&gt;Because members of staff group can edit this page, members of staff group can also edit the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;ACL&lt;/span&gt;, which is nothing more than a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;JSPWiki&lt;/span&gt; markup. This causes some potential security flaw: any member of staff group can edit &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;ACL&lt;/span&gt;, e.g., by mistake, and thus violate the intended access control of this page. Ideally, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;ACL&lt;/span&gt;, though residing in a page, should be treated differently from the other page source. &lt;/p&gt; &lt;p&gt;Thus an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;ACL&lt;/span&gt; Filter is introduced to only allow users with &lt;a class="wikipage" href="http://www.jspwiki.org/wiki/AllPermission"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;AllPermission&lt;/span&gt;&lt;/a&gt; to create/edit/delete in-page &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;ACL&lt;/span&gt;. For instance, in the above example, even any member of staff group can edit the page, but only users with &lt;a class="wikipage" href="http://www.jspwiki.org/wiki/AllPermission"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;AllPermission&lt;/span&gt;&lt;/a&gt; can change the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;ACL&lt;/span&gt; to something other than the above &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;ACL&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_19"&gt;Essentially&lt;/span&gt;, the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;ACL&lt;/span&gt; Filter is trying to separate two concerns, content and access control over content, which are originally mixed up in the wiki markup. With the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;ACL&lt;/span&gt; Filter, content and access control over content are treated &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_22"&gt;differently&lt;/span&gt;: any one authorised by ACLs can edit content, but only some certain super users can edit access control.&lt;br /&gt;&lt;/p&gt;This work has been contributed back the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;JSPWiki&lt;/span&gt; community. See &lt;a href="http://www.jspwiki.org/wiki/ACLFilter"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-9000659721761522061?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/9000659721761522061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=9000659721761522061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/9000659721761522061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/9000659721761522061'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/jspwiki-acl-filter.html' title='JSPWiki ACL Filter'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3318268864619455665</id><published>2008-11-04T11:00:00.002Z</published><updated>2008-11-04T11:58:46.626Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Spring JUnit Test and Rollback DB Transaction</title><content type='html'>In &lt;a href="http://www.springframework.org/"&gt;Spring&lt;/a&gt;, doing unit test with JUnit4 can be as simple as this:&lt;br /&gt;&lt;br /&gt;@RunWith(SpringJUnit4ClassRunner.class)&lt;br /&gt;@ContextConfiguration&lt;br /&gt;public class HibernateDaoTest {   &lt;br /&gt;    @Autowired&lt;br /&gt;    protected RepositoryHibernateDao repositoryHibernateDao;&lt;br /&gt;   &lt;br /&gt;    @Test&lt;br /&gt;    @Transactional&lt;br /&gt;    public void submitProject() {&lt;br /&gt;        Project newp = new Project();&lt;br /&gt;        newp.setStatus("PENDING");    &lt;br /&gt;        int pid = repositoryHibernateDao.save(newp);&lt;br /&gt;        assertTrue(pid &gt; 0);       &lt;br /&gt;        Project p = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;repositoryHibernateDao&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;getProjectDetail&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;pid&lt;/span&gt;);&lt;br /&gt;        &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;assertEquals&lt;/span&gt;(p.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;getName&lt;/span&gt;(), name);&lt;br /&gt;        &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;assertEquals&lt;/span&gt;(p.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;getSubmitUser&lt;/span&gt;(), owner);       &lt;br /&gt;        &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;repositoryHibernateDao&lt;/span&gt;.delete(p);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;With the annotation @Transactional, when the test is finished, the database is supposed to roll back to the state before the test. But this does not happen in my Spring/Hibernate/MySQL setting.&lt;br /&gt;&lt;br /&gt;It turns out to be that in order to support transaction, the MySQL table must be an &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;InnoDB&lt;/span&gt;&lt;/span&gt; table.&lt;br /&gt;&lt;br /&gt;Usually the tables are &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;MyISAM&lt;/span&gt;&lt;/span&gt; ones, which are non-transactional. The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;MyISAM&lt;/span&gt; table provides high-speed storage and retrieval, as well as &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;fulltext&lt;/span&gt;         searching capabilities. It is supported         in all MySQL configurations, and is the default storage engine         unless you have configured MySQL to use a different one by         default.&lt;br /&gt;       &lt;br /&gt;On the other hand, the &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;InnoDB&lt;/span&gt; &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;BDB&lt;/span&gt;&lt;/span&gt; storage         engines provide transaction-safe tables. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;InnoDB&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;is included by default in all MySQL         5.0 binary distributions. &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/converting-tables-to-innodb.html"&gt;Here&lt;/a&gt; describes how to&lt;br /&gt;Convert a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;MyISAM&lt;/span&gt; table to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;innoDB&lt;/span&gt;. Basically, what needs to be done is: ALTER TABLE ... ENGINE=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;INNODB&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3318268864619455665?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3318268864619455665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3318268864619455665' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3318268864619455665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3318268864619455665'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/spring-junit-test-and-rollback-db.html' title='Spring JUnit Test and Rollback DB Transaction'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6137719001850640471</id><published>2008-11-03T14:31:00.000Z</published><updated>2008-11-04T11:38:49.822Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google Maps'/><title type='text'>Map of Downloads</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T3RexjHEbhs/SRAxFNpVp1I/AAAAAAAAAnI/OmvQL-LcWqQ/s1600-h/download_map.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 226px;" src="http://4.bp.blogspot.com/_T3RexjHEbhs/SRAxFNpVp1I/AAAAAAAAAnI/OmvQL-LcWqQ/s400/download_map.PNG" alt="" id="BLOGGER_PHOTO_ID_5264761930028263250" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I have used &lt;a href="http://code.google.com/apis/maps/"&gt;Google Maps API&lt;/a&gt; to display on the map where the downloads of OMII-UK software are from. See the downloads for &lt;a href="http://www.omii.ac.uk/repository/download_map.jhtml?rid=403"&gt;Grimoires 2.0.0&lt;/a&gt;. By clicking on the balloon, more geographic information about the download will pop up. For instance, I know there is a guy in&lt;span style="font-size:100%;"&gt; Changsha, Hunan, China&lt;/span&gt; has downloaded Grimoires 2.0.0. All the other downloads are from UK, France and Germany.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6137719001850640471?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6137719001850640471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6137719001850640471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6137719001850640471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6137719001850640471'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/map-of-downloads.html' title='Map of Downloads'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T3RexjHEbhs/SRAxFNpVp1I/AAAAAAAAAnI/OmvQL-LcWqQ/s72-c/download_map.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6169816725993332475</id><published>2008-11-03T14:27:00.002Z</published><updated>2008-11-04T11:15:13.018Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Hibernate Performance</title><content type='html'>(This is one of my old Google Notes.)&lt;br /&gt;&lt;br /&gt;I have used &lt;a href="http://www.yourkit.com/"&gt;YourKit&lt;/a&gt; to benchmark the performance of &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt; some time ago.&lt;br /&gt;&lt;br /&gt;In my database, I have two tables: Project and Release. Project is associated with release in a one-to-many relationship. In my setting, a SQL statement using JDBC costs from several milliseconds to ~30 milliseconds; serving a JSP costs from 1 second to 3 seconds in the first run, then from tens of milliseconds to ~250 milliseconds in the later run.&lt;br /&gt;&lt;br /&gt;In Hibernate,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Getting a single project (as well as its releases) costs 234ms in the first run, and 14ms in average (excluding the first run);&lt;/li&gt;&lt;li&gt;Getting all projects costs 547ms in the first run, and 96ms in average;&lt;/li&gt;&lt;li&gt;Getting some partial information of all projects, costs 282ms in the first run, and 15ms in average.&lt;/li&gt;&lt;/ul&gt;The reason for that the first run is much slower, is because Hibernate does bytecode instrumentation to generate proxy object on the first touch of ORM, which is quite expensive. However, the late runs approximate JDBC's performance.&lt;br /&gt;&lt;br /&gt;Some Hibernate tips:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.hibernate.org/hib_docs/v3/reference/en-US/html/performance.html"&gt;Chapter 19 of the Hibernate reference&lt;/a&gt; describes how to improve its performance.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use set instead of list. List uses the id as index, thus creates a large data structure with lots of empty cells.&lt;/li&gt;&lt;li&gt;Associated objects are initialized in a lazy way. They need to be touched to bring into memory.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6169816725993332475?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6169816725993332475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6169816725993332475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6169816725993332475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6169816725993332475'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/hibernate-performance.html' title='Hibernate Performance'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-283138166192273513</id><published>2008-11-02T14:25:00.002Z</published><updated>2008-11-04T11:16:20.284Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Pattern'/><title type='text'>Dependency Resolution</title><content type='html'>(This is one of my old Google Notes.)&lt;br /&gt;&lt;br /&gt;In the software architecture, one component (caller) is relying on some services provided by another component (callee). Before the caller can use the service of the caller, the caller must hold an instance of the callee. There are several ways to do it.&lt;br /&gt;&lt;br /&gt;First, the caller can create an instance of the callee. Sometimes, only one instance of the callee is preferred to exist in the whole system, because it is unique or it is expensive to create, e.g., the database manager. In that case, &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;the singleton pattern&lt;/a&gt; can be used. But there are some shortcomings with the singleton pattern. First, because the callee has to implement the singleton pattern and the callers have to invoke the singleton pattern in a proper way, the code of solving dependency is scattering around the whole system. Second, it is inflexible to replace a callee component with one of the same interface.&lt;br /&gt;&lt;br /&gt;Second, the caller can go to a &lt;a href="http://java.sun.com/blueprints/patterns/ServiceLocator.html"&gt;"service locator"&lt;/a&gt;, then use, for instance, a JNDI directory to locate callees. Though the service locator maintains a central place of managing all service providers (callees), the caller still needs to know how to talk to the service locator.&lt;br /&gt;&lt;br /&gt;Third, this is state-of-the-art: &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;dependency injection&lt;/a&gt;, which is implemented in many frameworks, such as &lt;a href="http://www.springframework.org/"&gt;Spring&lt;/a&gt; and &lt;a href="http://code.google.com/p/google-guice/"&gt;Google Guice&lt;/a&gt;. Compared to the above two approaches, the advantages of dependency injection are obvious. Both caller and callee can be POJO (Plain Old Java Object), with no special control implemented. And there is a single control point. In Spring, that is the Spring XML configuration file. Thus the dependency is solved in a declarative way! Nowadays we always prefer a declarative way to a programmatic way to do things.&lt;br /&gt;&lt;br /&gt;In a service-oriented architecture, service workflow is a multi-component system. Any component service can be a caller, a callee, or both. There is some similarity between dependency injection and how a workflow is composed: both have a central control point for solving dependency in a declarative way. In workflow, that is the workflow description file, e.g., written using BPEL. On the other hand, in service-oriented architecture, the&lt;b&gt; &lt;/b&gt;service registry shares a similar idea as the service locator pattern.&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-283138166192273513?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/283138166192273513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=283138166192273513' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/283138166192273513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/283138166192273513'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/11/dependency-resolution.html' title='Dependency Resolution'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5846443268926284498</id><published>2008-10-31T09:56:00.007Z</published><updated>2009-10-27T15:38:05.805Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java Profiling'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='Troubleshooting'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><title type='text'>Tomcat Troubleshooting</title><content type='html'>The OMII-UK website is a Java web application running in Tomcat, which sits behind an Apache web server. Several methods are there for monitoring and troubleshooting it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monitoring&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First, a simple web monintor is running on another machine, and checking the contents of several important web pages every 15 minutes. If anything goes wrong, I will get an email notification. Of course, this task can also be done by &lt;a href="http://www.nagios.org/"&gt;Nagios&lt;/a&gt;. The advantage of using my own web monitor instead of a complicated monitor system like Nagios, is that I have full control over what to inspect. For instance, I am able to detect that although Tomcat is still OK but the database connection is down.&lt;br /&gt;&lt;br /&gt;Second, in the Java web applicaiton, which is based on &lt;a href="http://www.springframework.org/"&gt;the Spring Framework&lt;/a&gt;, &lt;a href="http://static.springframework.org/spring/docs/2.0.x/reference/aop.html"&gt;Spring AOP&lt;/a&gt; (Aspect Oriented Programming) is leveraged to monitor the performance of all servlets. If it takes any servlet more than a pre-defined threshold to serve a request, I'll get an email notification. The threshold, currently set to 200ms, is defined in Spring XML configuration file.&lt;br /&gt;&lt;br /&gt;Third, Tomcat is started with "-Dcom.sun.management.jmxremote", which enables local &lt;a href="http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html"&gt;jconsole&lt;/a&gt; connection. JDK 1.5 is used. In JDK 1.6, jconsole support is default, so no need to set a JVM option to enable it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What if something goes wrong ...&lt;/span&gt;&lt;br /&gt;&lt;ol id="vsng4"&gt;&lt;li id="o:vq0"&gt;Check Apache web server only. http://hostname/server-status.  You may need to modify httpd.conf to enable this.&lt;br /&gt;&lt;/li&gt;&lt;li id="zefv"&gt;Check Tomcat only. http://hostname:8080.&lt;br /&gt;&lt;/li&gt;&lt;li id="zefv0"&gt;Check jconsole-&gt;Memory. See if JVM runs out of memory.&lt;/li&gt;&lt;li id="zefv0"&gt;Check Tomcat logs, Apache logs and database log.&lt;/li&gt;&lt;li id="qr35"&gt;Last but not least important, use &lt;a href="http://logging.apache.org/chainsaw/"&gt;Chainsaw&lt;/a&gt; to check log4j.xml. Chainsaw is a GUI, which makes it easy to browse log4j's log. The log4j configuration may look like:&lt;/li&gt;&lt;/ol&gt;log4j.appender.FileLog = org.apache.log4j.RollingFileAppender&lt;br /&gt;log4j.appender.FileLog.MaxFileSize    = 10MB&lt;br /&gt;log4j.appender.FileLog.MaxBackupIndex = 14&lt;br /&gt;log4j.appender.FileLog.File=$CATALINA_HOME/logs/log4j.xml&lt;br /&gt;log4j.appender.FileLog.layout = org.apache.log4j.xml.XMLLayout&lt;br /&gt;log4j.rootCategory=WARN,FileLog&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Let's say there is a memory leak or something inside the Java web application is wrong ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are various JVM options that allow us to debug or profile Java web application:&lt;br /&gt;&lt;ul id="m8ck"&gt;&lt;li id="m8ck0"&gt;Frequently used server VM options: -server -Xms512m -Xmx512m&lt;br /&gt;&lt;/li&gt;&lt;li id="lo2m0"&gt;jconsole support: -Dcom.sun.management.jmxremote&lt;br /&gt;&lt;/li&gt;&lt;li id="lo2m2"&gt;Dump heap on running out of memory: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/root/heapdump &lt;/li&gt;&lt;li id="lo2m2"&gt;Enable debugging: -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000&lt;/li&gt;&lt;li id="lo2m5"&gt;Enable YourKit profiling: -agentlib:yjpagent&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://www.yourkit.com/"&gt;YourKit&lt;/a&gt; is a very good Java profiling tool, and it has a free licence for open source projects. That is what I am using. To enable profiling manually, see &lt;a href="http://www.yourkit.com/docs/75/help/getting_started/running_with_profiler/agent.jsp"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;ul id="c6e4"&gt;&lt;li&gt;On Windows, 32-bit, add &lt;i id="fvca1"&gt;&lt;yourkit&gt;&lt;/yourkit&gt;&lt;/i&gt;\bin\win32 to the (SYSTEM) PATH.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;On Linux x86, 32-bit, add &lt;yourkit&gt;/bin/linux-x86-32 to the LD_LIBRARY_PATH. &lt;/yourkit&gt;&lt;/li&gt;&lt;li id="oeq_"&gt;Check whether it is working: java -agentlib:yjpagent=help&lt;/li&gt;&lt;li id="rxp1"&gt;Profiling: java -agentlib:yjpagent&lt;/li&gt;&lt;li id="b9r_"&gt;Do not forget to force garbage collection before capture memory.&lt;/li&gt;&lt;/ul&gt;I also have a stress test tool that replays saved Apache/Tomcat access logs.&lt;img style="border: 1px solid blue; z-index: 90; position: absolute; left: 30px; top: 81px;" id="smallDivTip" src="chrome://dictionarytip/skin/book.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5846443268926284498?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5846443268926284498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5846443268926284498' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5846443268926284498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5846443268926284498'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/10/tomcat-trouble-shooting.html' title='Tomcat Troubleshooting'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4923231960097527442</id><published>2008-10-30T10:57:00.007Z</published><updated>2008-10-30T11:32:08.508Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache web server'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><title type='text'>Pass Apache Authentication to Tomcat</title><content type='html'>It costs me several hours to figure this out. So I think it is worthy writing it down.&lt;br /&gt;&lt;br /&gt;I have an Apache web server (2.2.3) sitting in front of Tomcat (5.5.27). In Apache configuration, I have:&lt;br /&gt;&lt;br /&gt;&amp;lt;location&gt;&lt;br /&gt;    AuthType Basic&lt;br /&gt;    AuthName "Secure Service"&lt;br /&gt;    AuthUserFile /etc/httpd/conf/user.db&lt;br /&gt;    require valid-user&lt;br /&gt;&amp;lt;/location&gt;&lt;br /&gt;&lt;br /&gt;If the authentication succeeds, the HTTP request is passed to Tomcat by mod_proxy_ajp:&lt;br /&gt;&lt;br /&gt;ProxyPass /secure/ ajp://localhost:8009/secure/&lt;br /&gt;&lt;br /&gt;In Tomcat server.xml, I disable the Tomcat authentication in the AJP connector (both tomcatAuthenticaiton and request.tomcatAuthentication work):&lt;br /&gt;&lt;br /&gt;&amp;lt;Connector port="8009" enablelookups="false" redirectport="8443" protocol="AJP/1.3" address="127.0.0.1" tomcatauthentication="false"&gt;&lt;br /&gt;&lt;br /&gt;If the authentication succeeds, Apache will create an HTTP head:&lt;br /&gt;&lt;br /&gt;REMOTE_USER = omii&lt;br /&gt;&lt;br /&gt;But in Tomcat, I do not see the REMOTE_USER header. Instead, I see&lt;br /&gt;&lt;br /&gt;authorization = Basic b3ip9kd9dkekd9&lt;br /&gt;&lt;br /&gt;It turns out that Tomcat puts the Apache authentication information in the form of a user principal, which can be accessed by the following code inside a JSP page:&lt;br /&gt;&lt;br /&gt;java.security.Principal pr = request.getUserPrincipal();&lt;br /&gt;if (pr != null) String r = pr.getName(); // r.equals("omii")&lt;/connector&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4923231960097527442?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4923231960097527442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4923231960097527442' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4923231960097527442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4923231960097527442'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/10/pass-apache-authentication-to-tomcat.html' title='Pass Apache Authentication to Tomcat'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3629725875994913305</id><published>2008-10-30T09:16:00.006Z</published><updated>2008-10-30T10:35:55.924Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Shibboleth'/><title type='text'>Shibboleth: Federated Trust</title><content type='html'>Having been developed for around 3 years, &lt;a href="http://shibboleth.internet2.edu/"&gt;Shibboleth&lt;/a&gt; provides web single sign on and attribute exchange, which together build up a trust federation.&lt;br /&gt;&lt;br /&gt;Like many ideas in computer science, Shibboleth is also about &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;&lt;span style="font-style: italic;"&gt;separation of concerns&lt;/span&gt;&lt;/a&gt;. Two pairs of concerns have been identified and separated in architecting Shibboleth: Service Provider (SP) has been separated from Identity Provider (IdP), and identity has been separated from attributes.&lt;br /&gt;&lt;br /&gt;By separating IdP from SP, an SP, i.e., a Shibboleth protected web application, is free of maintaining a user database and perform authentication, which are delegated to some appropriate IdP. Though SP may still needs to enforce local authorization decisions. the WAYF (Where Are You From) service is leveraged as a means to locate a suitable IdP that is able to authenticate a user who want to access SP.&lt;br /&gt;&lt;br /&gt;By separating attributes from identity, flexibility is achieved on how to represent an authenticated user. Let's say I try to access an SP and I use University of Southampton's IdP to authenticate myself. As a result of the authentication, I will get two attributes: one is eduPersonPrincipalName, i.e, my name; the other is eduPersonRole, in my case, that is research staff. My IdP does not need to give out my eduPersonPrincipalName to the SP. Instead giving out the eduPersonRole attribute might sufficiently entitle me to the service. In this way, my privacy is somehow protected even when I am granted the access.&lt;br /&gt;&lt;br /&gt;Shibboleth is built over &lt;a href="http://en.wikipedia.org/wiki/SAML"&gt;SAML&lt;/a&gt;. If you look at &lt;a href="https://spaces.internet2.edu/display/SHIB2/TechnicalSpecs"&gt;Shibboleth technical specs&lt;/a&gt;, SAML specs add up to several hundred pages, while the Shibboleth architecture specification has only 19 pages.  SAML defines core (XML schema for SAML assertions and protocol message elements), protocol (what is transmitted), binding (how the protocol messages are transmitted) and profiles ( a concrete manifestation of a defined use case using a particular combination of assertions, protocols, and bindings).&lt;br /&gt;&lt;br /&gt;Shibboleth promotes a trust federation. It is the responsibility of the federation that decides which SP and IdP can join the federation. Thus the trust between a user and an SP is maintained by the federation. A peace of mind for users.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Openid"&gt;OpenID&lt;/a&gt; is another technology for web single sign on. Different from Shibboleth, there is no such a federation in the OpenID architecture. Thus it is down to users who decide whether they should trust a service provider and use their OpenIDs on the service provider's website. I am not happy with it.  I also do not think it is a very good idea to use a single OpenID to access websites with different information confidentiality levels, such as online banking, webmail and a simple web-based game site. Clearly online banking has the highest level in terms of information confidentiality, the game site has the lowest, and webmail sits between them.&lt;br /&gt;&lt;br /&gt;In UK, &lt;a href="http://www.ukfederation.org.uk/"&gt;UK Federation&lt;/a&gt; manages a Shibboleth federation for eduation can research. &lt;a href="http://www.ukfederation.org.uk/content/Documents/MemberList"&gt;Here&lt;/a&gt; is the current membership, i.e., who provides SP and IdP. And here is &lt;a href="http://www.ukfederation.org.uk/content/Documents/AvailableServices"&gt;the list of all available services&lt;/a&gt; that support UK Federation managed Shibboleth authentication&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Edsger_W._Dijkstra" title="Edsger W. Dijkstra"&gt;Edsger W. Dijkstra&lt;/a&gt; in his 1974 paper "On the role of scientific thought" explains why separation of concerns is so important:&lt;br /&gt;&lt;blockquote&gt; &lt;p&gt;Let me try to explain to you, what to my taste is characteristic for all intelligent thinking. It is, that one is willing to study in depth an aspect of one's subject matter in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects. We know that a program must be correct and we can study it from that viewpoint only; we also know that it should be efficient and we can study its efficiency on another day, so to speak. In another mood we may ask ourselves whether, and if so: why, the program is desirable. But nothing is gained --on the contrary!-- by tackling these various aspects simultaneously. It is what I sometimes have called &lt;b&gt;"the separation of concerns"&lt;/b&gt;, &lt;span style="font-weight: bold;"&gt;which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts, that I know of.&lt;/span&gt; This is what I mean by "focusing one's attention upon some aspect": it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect's point of view, the other is irrelevant. It is being one- and multiple-track minded simultaneously.&lt;/p&gt; &lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3629725875994913305?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3629725875994913305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3629725875994913305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3629725875994913305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3629725875994913305'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/10/shibboleth-federated-trust.html' title='Shibboleth: Federated Trust'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8558285840700955842</id><published>2008-10-29T21:21:00.002Z</published><updated>2008-10-29T21:44:54.970Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Machine'/><title type='text'>Use Virtual Machine to Evaluate Software</title><content type='html'>Here at OMII-UK we need to evaluate software generated in the commissioned software project from time to time. For instance, now it is my duty to evaluate SPAM-GP, some JSR-168 portlets for security stuff.  I am using &lt;a href="http://www.vmware.com/products/server/"&gt;VMware Server&lt;/a&gt; to do this job. I think it is great! Basically, I build a virtual machine, in which I install, configure and test the software to be evaluated. Benefits by doing so are obvious:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It is a VM, where the software is running. So it has all advantages as we dedicate a physical machine to the software. This is a working instance, and we can keep it as long as we wish. It is also easy for someone else who wants to see a demo or to play with it.&lt;/li&gt;&lt;li&gt;Compared to a physical machine, the VM only costs around 3GB disk space. Sounds quite large, but it is little in my 200GB harddisk.&lt;/li&gt;&lt;/ul&gt;VMware Server supports snapshot. A snapshot is a persistent state of the whole VM. It can be used to save the current state of the VM, which we are happy with. Then we can carry on manipulating the VM and come back to the snapshot whenever we want. But unfortunately, in VMware Server, only one snapshot can be taken for each VM.  A newly taken snapshot will simply replace the previous one.&lt;br /&gt;&lt;br /&gt;My machine has 1GB memory. So sometimes it is slow to run VMware server, particularly when two VMs are running at the same time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8558285840700955842?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8558285840700955842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8558285840700955842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8558285840700955842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8558285840700955842'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2008/10/use-virtual-machine-to-evaluate.html' title='Use Virtual Machine to Evaluate Software'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2536795686431155162</id><published>2007-07-22T11:13:00.000+01:00</published><updated>2007-07-23T12:00:58.102+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>WTP Europa Release</title><content type='html'>&lt;a href="http://www.eclipse.org/europa/"&gt;     Eclipse Europa&lt;/a&gt; is the annual release of Eclipse projects of 2007. Here are some of my experience about it. Since I am using &lt;a href="http://www.eclipse.org/webtools/main.php"&gt;WTP&lt;/a&gt; mostly, my experience is mainly concerned with WTP.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Interesting, my&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;&lt;a href="http://www.eclipse.org/webtools/releases/2.0/index.php"&gt;WTP 2.0&lt;/a&gt; can not start up with -Xmx1024m. &lt;/span&gt;&lt;span&gt;But it is able to start up with a smaller maximum heap size, for instance, -Xmx768m. While my other Java application, such as Tomcat, has no problem with -Xmx1024m. I am using JDK &lt;/span&gt;1.6.0_01. I posted a message at the eclipse.webtools newsgroup. I will follow this issue.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;It is desirable that WS explorer has an extension point to support application domain service description document (non WSDL). &lt;/span&gt;WS explorer can be used as a &lt;a href="http://www.uddi.org/"&gt;UDDI&lt;/a&gt; browser. In UDDI data model, the service entity can be associated with a tModel, which is simply a link to some non-registered document that further describes the service, for instance, the WSDL of the service. WS explorer supports to retrieve the WSDL, visually display it, and even invoke its operations.&lt;br /&gt;&lt;br /&gt;I am working on the &lt;a href="http://www.grimoires.org/"&gt;Grimoires&lt;/a&gt; project, which is an extended UDDI service registry supporting metadata annotation and service discovery by interface signature.  In our practice, we very often see that users design their own service description language, instead of WSDL, to describe their services. For instance, the &lt;a href="http://www.mygrid.org.uk/"&gt;myGrid&lt;/a&gt; project, an influential service-oriented bioinformatics experiment environment, uses its own Feta schema. &lt;a href="http://www.globus.org/toolkit/mds/glueschemalink.html"&gt;GLUE&lt;/a&gt; is a popular schema to describe services and resources in &lt;a href="http://en.wikipedia.org/wiki/Grid_computing"&gt;grid computing&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;explorer has an extension point to support application domain service description document (non- explorer to open it; if it points to some non-This is understandable. First, it is cheap to design an XML schema for their XML-based service description language.  Second, it improves usability with a DSL (domain specific language)  in place.  According to UDDI' data model, the URL of domain specific service description documents can be put into a tModel, then associated with the service entity.  Thus it is desirable that WSWSDL). That is, if the tModel points to WSDL, then WS explorer uses its embedded WSDLWSDL document, the WS explorer uses some extension registered corresponding explorer to visually handle it. Somehow UDDI's tModel can be considered as an extension point of UDDI data model, because it allows any document with a URL to be associated with a service.&lt;br /&gt;&lt;br /&gt;The benefit of such an extension point in WS explorer is to improve usability by supporting domain-specific service description documents, which further enhances the expressiveness of service description: whether the description document is WSDL or non-WSDL, standard based or domain specific, current supported or emerging, all can be handled by WS explorer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Another desirable feature is about being able to print&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;visualized XSD/WSDL&lt;/span&gt; supports visualizing . WTPXSD/WSDL. The visualized result is very informative and is a good source to be put into documentation. But this is not supported a couple of years ago. It is very good that now WTP 2.0 supports printing visualized XSD! (Although I am not sure exactly since which version WTP has implemented this.) But the printed visualized XSD loses its icons standing for XSD attribute and element. And it still does not allow to print visualized WSDL. I am not sure whether there is some technical difficulty for printing contents of arbitrary editors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2536795686431155162?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2536795686431155162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2536795686431155162' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2536795686431155162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2536795686431155162'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/07/wtp-europa-release.html' title='WTP Europa Release'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5575734883163445070</id><published>2007-06-14T20:11:00.000+01:00</published><updated>2007-06-14T20:13:21.677+01:00</updated><title type='text'>"An open source project would be nothing without a supporting community"</title><content type='html'>"An open source project would be nothing without a supporting community."&lt;br /&gt;    - from Eclipse' FAQ&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5575734883163445070?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5575734883163445070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5575734883163445070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5575734883163445070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5575734883163445070'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/06/open-source-project-would-be-nothing.html' title='&quot;An open source project would be nothing without a supporting community&quot;'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4682232679808270293</id><published>2007-05-30T21:07:00.000+01:00</published><updated>2007-05-30T21:37:38.621+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web service'/><title type='text'>Selling Data Through Web Service</title><content type='html'>&lt;a href="https://www.strikeiron.com/default.aspx"&gt;StrikeIron&lt;/a&gt;, "data as a service", provides a marketplace where people can put web services or purchase hits on web services that make available data which value is dependent on time, for instance, foreign currency exchange rates.&lt;br /&gt;&lt;br /&gt;The key of business model is to sell valuable real time streamed data. And WS is adopted to simplify the data service implementation. The idea is cool and simple. And seems it works. I mean StrikeIron does have quite a few customers.&lt;br /&gt;&lt;br /&gt;By googling "web serivces marketplace", I am aware &lt;a href="http://news.zdnet.co.uk/internet/0,1000000097,39211251,00.htm"&gt;Amazon has filed a patent of web services marketplace on 2005&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If someone is able to build up valuable data by doing data mining on Internet with the help of tools like google,  and use StrikeIron to host a WS to provide the data, then (s)he can make money!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4682232679808270293?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4682232679808270293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4682232679808270293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4682232679808270293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4682232679808270293'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/selling-data-through-web-service.html' title='Selling Data Through Web Service'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5241536308478268920</id><published>2007-05-29T10:19:00.000+01:00</published><updated>2007-05-29T10:32:47.682+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>AJAX Enabled GrimoiresScript Interpreter</title><content type='html'>I implemented &lt;a href="http://runtime32.blogspot.com/2007/05/toy-language-to-handle-grimoires.html"&gt;a toy language&lt;/a&gt; to handle Grimoires registry, which now I renamed as GrimoiresScript. Now I created a web-based GrimoiresScript interpreter, using AJAX to communicate between HTML page that takes in user input, and server-side JSP that invokes GrimoiresScript interpretation engine. The implementation follows &lt;a href="http://www.w3schools.com/ajax/ajax_example.asp"&gt;the example in w3schools' AJAX tutorial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;AJAX is nothing but, or mostly a JavaScript RMI, which enables HTML pages to invoke remote methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5241536308478268920?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5241536308478268920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5241536308478268920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5241536308478268920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5241536308478268920'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/ajax-enabled-grimoiresscript.html' title='AJAX Enabled GrimoiresScript Interpreter'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-34707706206882358</id><published>2007-05-25T23:09:00.000+01:00</published><updated>2007-05-25T23:27:11.197+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Web Services Explorer in Eclipse</title><content type='html'>&lt;a href="http://www.eclipse.org/webtools/jst/components/ws/M4/tutorials/WebServiceExplorer.html"&gt;Web services explorer&lt;/a&gt; in eclipse can be used to browse &lt;a href="http://www.uddi.org/"&gt;UDDI&lt;/a&gt; registries, to parse services' WSDLs, and even to invoke service operations by sending them SOAP messages. It is implemented as a web application running on eclipse' embeded application server. So I am thinking to turn it into a standalone web application to act as Grimoires' web-based interface. As Chris Brealey &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=89101"&gt;pointed out&lt;/a&gt;, the &lt;a href="http://www.eclipse.org/webtools/main.php"&gt;WTP&lt;/a&gt; team also has this idea, but it is not easy to do this and the WTP team simply has no resource to be allocated on this. I played web services explorer today. It relies on quite a lot eclipse plug-ins. Even it could be turned into a standalone web application, it would be of a large footprint.&lt;span style=";font-family:sans-serif;font-size:85%;"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-34707706206882358?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/34707706206882358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=34707706206882358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/34707706206882358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/34707706206882358'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/web-services-explorer-in-eclipse.html' title='Web Services Explorer in Eclipse'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8868872947159867990</id><published>2007-05-24T21:20:00.001+01:00</published><updated>2007-05-24T21:39:52.803+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Monitor Memory Usage in Java</title><content type='html'>There is no "sizeof" in Java. Originally there was no way to check or estimate how much memory has been used in Java. But since Java 1.5, we can use &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/management/index.html"&gt;the Monitoring and Management facility&lt;/a&gt; to monitor memory usage.  The following code&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();         &lt;br /&gt;System.out.println(mbean.getHeapMemoryUsage().toString();&lt;br /&gt;System.out.println(mbean.getNonHeapMemoryUsage().toString();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;will print out&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;init = 0(0K) used = 319360(311K) committed = 2031616(1984K) max = 66650112(65088K)&lt;br /&gt;init = 8585216(8384K) used = 2379416(2323K) committed = 8880128(8672K) max = 100663296(98304K)&lt;br /&gt;&lt;/pre&gt;MemoryMXBean is also able to send out notification when some memory usage threshold is met.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8868872947159867990?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8868872947159867990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8868872947159867990' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8868872947159867990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8868872947159867990'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/monitor-memory-usage-in-java.html' title='Monitor Memory Usage in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1930704361046322004</id><published>2007-05-24T10:11:00.000+01:00</published><updated>2007-05-24T21:39:24.557+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Call Google AJAX Search Service in Java</title><content type='html'>Google has both a SOAP style service and an AJAX style for search. But it seems google focuses on the AJAX style rather than the SOAP style. For instance, the AJAX style has more functionalities than the SOAP style.&lt;br /&gt;&lt;br /&gt;At the client side, the AJAX style is implemented as Javascripts embeded in a HTML page, which makes it impossible to be called from &lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/index.html"&gt;JDK script engine&lt;/a&gt;, at least not in a straightforward way.&lt;br /&gt;&lt;br /&gt;Davanum Srinivas has published &lt;a href="http://blogs.cocoondev.org/dims/archives/004722.html"&gt;an interesting blog&lt;/a&gt; on how to call google ajax search service in Java. He used an reverse engineering approach to capture the url that the javascript sent to the google server, by some TCP/IP monitor. By manipulate the captured url, it is able to call google search in Java. The url looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;"http://www.google.com/uds/GwebSearch?"callback=GwebSearch.RawCompletion&amp;context=0&amp;amp;&lt;br /&gt;lstkp=0&amp;&lt;br /&gt;rsz=small&amp;amp;&lt;br /&gt;hl=en&amp;&lt;br /&gt;sig=8656f49c146c5220e273d16b4b6978b2&amp;amp;&lt;br /&gt;q=Axis2&amp;&lt;br /&gt;key=xxxxxxxxxxxxxxxxxx&amp;amp;&lt;br /&gt;v=1.0"&lt;/pre&gt;&lt;br /&gt;When rsz is set to small, four records are returned; when large, eight are returned.&lt;br /&gt;&lt;br /&gt;The search result contains &lt;a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html#_intro_GResult"&gt;result objects&lt;/a&gt; in &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; format, which can be parsed using some &lt;a href="http://www.json.org/java/index.html"&gt;JSON parser&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It is easy to call google AJAX search service in Java. The challenge is when we have the capability to google repeatedly, untiredly, in brute force, or in a massive way, anything interesting can we achieve then?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1930704361046322004?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1930704361046322004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1930704361046322004' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1930704361046322004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1930704361046322004'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/call-google-ajax-search-service-in-java.html' title='Call Google AJAX Search Service in Java'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7265610901770829402</id><published>2007-05-23T14:08:00.000+01:00</published><updated>2007-05-24T21:40:46.495+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grimoires'/><title type='text'>Bridge GLUE LDAP schema and GLUE XML schema</title><content type='html'>&lt;a href="http://glueschema.forge.cnaf.infn.it/"&gt;GLUE&lt;/a&gt; is an information model to describe Grid resources. It has both an LDAP schema and an XML schema as its concrete data models. Usually GLUE data is in LDAP DIT in Grids. I need to read the LDAP data, convert to XML data according to GLUE schema, and then publish into &lt;a href="http://www.grimoires.org/"&gt;Grimoires&lt;/a&gt; registry. What I am doing is:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use JAXB to generate Java bean classes according to GLUE XML schema;&lt;/li&gt;&lt;li&gt;Parse GLUE LDAP schema with the help of an ANTLR-based LDAP schema parser, and generate Java code that converts LDAP entries to Java beans using the classes generated in step 1;&lt;/li&gt;&lt;li&gt;Use JNDI to read GLUE LDAP DIT, call the code generated in step 2 to create beans that are further serialized to XML (in GLUE schema) by JAXB;&lt;/li&gt;&lt;li&gt;Publish GLUE XML to Grimoires through the XMLView interface, which takes the configuration of XSLT between GLUE schema and Grimoires schema.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7265610901770829402?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7265610901770829402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7265610901770829402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7265610901770829402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7265610901770829402'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/bridge-glue-ldap-schema-and-glue-xml.html' title='Bridge GLUE LDAP schema and GLUE XML schema'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-3829309010465661599</id><published>2007-05-23T13:44:00.000+01:00</published><updated>2007-05-24T21:38:50.455+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Grimoires'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>A Toy Language to Handle Grimoires Registry</title><content type='html'>I created a toy language to handle &lt;a href="http://www.grimoires.org/"&gt;Grimoires&lt;/a&gt; registry using &lt;a href="http://www.antlr.org/"&gt;ANTLR&lt;/a&gt;. It also has a simple GUI to type and run the script.  So I can type something like:&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;publish business (name="BusinessAA", desc="a business") -&gt; $bk.&lt;br /&gt;&lt;br /&gt;publish service (name="ServiceAA", desc="a service",bkey=$bk, wsdl="http://a/b/c.wsdl", address="http://a/b/") -&gt; $sk.&lt;br /&gt;&lt;br /&gt;attach metadata (type="http://www.grimoires.org/QoS", value="very good") to service (skey=$sk).&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If run this script, it will first publish a business with name and description, and save the business key to a variable $bk, which will later be used in publishing service. It then will publish a service and attach a metadata to the published service.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-3829309010465661599?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/3829309010465661599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=3829309010465661599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3829309010465661599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/3829309010465661599'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/05/toy-language-to-handle-grimoires.html' title='A Toy Language to Handle Grimoires Registry'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4678070539171592137</id><published>2007-04-02T16:15:00.000+01:00</published><updated>2007-04-02T16:23:34.788+01:00</updated><title type='text'>Google launches TiSP — Free wireless broadband</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.google.com/tisp/images/4_plugin.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px;" src="http://www.google.com/tisp/images/4_plugin.jpg" alt="" border="0" /&gt;&lt;/a&gt;Google launches free  wireless broadband which makes use of local plumbing and sewage systems.&lt;br /&gt;&lt;br /&gt;The reason it is free is "We believe that all users deserve free, fast and sanitary online access. To offset the cost of providing the TiSP service, we use information gathered by discreet DNA sequencing of your personal bodily output to display online ads that are contextually relevant to your culinary preferences, current health status and likelihood of developing particular medical conditions going forward. "&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4678070539171592137?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4678070539171592137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4678070539171592137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4678070539171592137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4678070539171592137'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/04/google-launches-tisp-free-wireless.html' title='Google launches TiSP — Free wireless broadband'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-214639210387577981</id><published>2007-03-16T10:51:00.000Z</published><updated>2007-03-16T10:53:25.069Z</updated><title type='text'>Sun's Blackbox</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.sun.com/emrkt/blackbox/index.jsp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://www.sun.com/images/l0/l0_blackbox.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-214639210387577981?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/214639210387577981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=214639210387577981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/214639210387577981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/214639210387577981'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/03/suns-blackbox.html' title='Sun&apos;s Blackbox'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-726365286521587258</id><published>2007-03-15T16:21:00.000Z</published><updated>2007-03-15T16:23:15.365Z</updated><title type='text'>曾经历的桂林山水</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.lotour.com/imagessnapshot/20070206/s110024751.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://www.lotour.com/imagessnapshot/20070206/s110024751.JPG" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-726365286521587258?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/726365286521587258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=726365286521587258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/726365286521587258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/726365286521587258'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/03/blog-post_15.html' title='曾经历的桂林山水'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7590784012493838015</id><published>2007-03-14T14:42:00.000Z</published><updated>2007-03-14T14:43:34.854Z</updated><title type='text'>[摘自www.popyard.org] 国家机密文件：最新流行官场口诀</title><content type='html'>&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;现代企业职位新解：&lt;/b&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;总是在裁人，简称总裁；老是板着脸，所以称老板；总想监视人，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;所以叫总监；经常没道理，就叫经理；让领导秘密舒服，称为秘书。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;四清四不清：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;开啥会不清楚，开会坐哪清楚；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;谁送礼不清楚，谁没送清楚；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;谁干得好不好不清楚，该提拔谁清楚；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;和谁睡不清楚，睡觉干什么清楚。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;当代八乱：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;大棚把季节搞乱了，关系把程序搞乱了，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;级别把能力搞乱了，法官把法律搞乱了，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;公安把治安搞乱了，银子把官场搞乱了，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;事故把交通搞乱了，小姐把辈份搞乱了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最引人注目的哥哥──伟哥；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最年轻的奶奶──二奶；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最难设防的偷窃──偷情；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;最热闹的走廊──发廊 ；&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最畅销的书──女秘书。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;办公室守则：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;苦干实干，做给天看；东混西混，一帆风顺；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;任劳任怨，永难如愿；会捧会献，杰出贡献；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;尽职尽责，必遭指责；推托栽赃，邀功领赏！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;中央机关出上联：上级压下级，一级压一级级级加码马到成功；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;地方政府对下联：下层蒙上层，一层蒙一层层层掺水水到渠成。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;横批：和谐社会。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;官场日志：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;清晨起床，打拳；上午开会，打盹；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;中午吃饭，打嗝；下午上班，打哈；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;傍晚加班，打牌；晚上娱乐，打炮；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;半夜回家，打架。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;百姓语录：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;狠抓就是开会，管理就是收费，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;重视就是标语，落实就是动嘴，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;验收就是宴会，检查就是喝醉，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;研究就是扯皮，政绩就是神吹，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;汇报就是掺水。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;官场之最；&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最难找的地方──有关部门；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最难捉摸的官话──研究研究；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最神秘的机构──组织上；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最大的官──一把手；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最难管的东西──一张嘴；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最谦虚的时候──在上级面前；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最冠冕堂皇的语言──工作需要；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最易接受的行贿──您讲得真好！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最关心的信息──自己这次能否升迁；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最傻的高兴──你的问题组织上也考虑了 ；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;最无奈的选择──因为年龄！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;组织就是......&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;在你遇到难事时对你说：我们无能为力！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;在你遭遇用人不公时对你说：你要正确对待！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;在你合法权益受侵时对你说：你要顾全大局！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;在你受到诬陷时对你说 ：你要相信组织！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;组织部长：谁关心我 我就关心谁；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;纪委书记：谁不关心我 我就关心谁；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;宣传部长：谁关心我, 我就关心他的正面，谁不关心我, 我就关心他的反面;；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;市委书记：谁关心我 我就让组织部长关心他，谁不关心我 我就让纪委书记关心他。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;忙碌的公仆在包厢里，重要的工作在宴会里，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;干部的任免在交易里，工程的发包在暗箱里，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;该抓的工作在口号里，须办的急事在会议里，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;妥善的计划在抽屉里，应煞的歪风在通知里，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;扶贫的干部在奥迪里，宝贵的人才在悼词里，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;优质的商品在广告里，辉煌的数字在总结里。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;公务员素描：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;满腔热血投身社会，摸爬滚打终日疲惫；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;低三下四谋取地位，常年奔波天天喝醉；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;收入可怜啥都嫌贵，交往叩头处处破费；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;有用本事已经作废，不学无术擅长开会；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;口是心非阳奉阴违，溜须拍马寻找机会；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;青春年华如此狼狈，苟且偷生窝囊一辈！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;做人的难处：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;有钱吧，说你准变坏；没钱吧，说你真失败；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;有成就吧，说你会投机；没成就吧，说你没出息；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;有情人吧，说你真坏；没有情人吧，说你变态！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;中年烦恼：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;职务不高，工资不高，血压血脂血糖高；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;政治不突出，业务不突出，腰椎盘突出；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;大会不发言，小会不发言，前列腺发炎；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;炒菜糊，烧饭糊，麻将不胡。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;批评上级，官位难保；批评同级，关系难搞；&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;批评下级，选票减少；批评自己，自寻烦恼；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;批评老婆，她就乱跑；批评老公，他就乱搞；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;唉，麻烦透了！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;领导用过的叫文物，百姓用过的叫废物；&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;领导强词夺理叫坚持真理，百姓据理力争叫无理取闹；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;领导握百姓的手叫关怀，百姓握领导的手叫巴结；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;领导做蠢事叫轶事，百姓做错事叫傻子；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;领导情人叫小蜜，百姓情人叫破鞋。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;CCTV新闻联播的惊人发现：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;开会没有不隆重的，闭幕没有不胜利的，讲话没有不重要的，决议没有不通过的，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;鼓掌没有不热烈的，人心没有不鼓舞的，领导没有不重视的，进展没有不顺利的，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;问题没有不解决的，完成没有不超额的，成就没有不巨大的，竣工没有不提前的，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;接见没有不亲切的，中日没有不友好的，中美没有不合作的，交涉没有不严正的，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;会谈没有不圆满的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;男女有别定律：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;男人爱上女人会做诗，女人爱上男人会做梦；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;女人对男人往往朝思暮想，男人对女人往往朝秦暮楚；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;女人看家本领是撒娇，男人拿手好戏是撒谎。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;女人的幸福在于：他真的爱我，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;女人吻男人算是一种幸福，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;男人吻女人算是一种口福；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;当女人走投无路时她会和一个男人结婚，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;当男人走投无路时一个女人会和他离婚；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;做情人的时候女人会让男人心疼，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;做妻子的时候女人会让男人头疼。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;穷人富人论：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;欠个人的钱是穷人，欠国家的钱是富人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;喝酒看度数的是穷人，喝酒看牌子的是富人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;写书的是穷人，盗版的是富人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;吃家禽的是穷人，吃野兽的是富人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;耕种土地的是穷人，买卖土地的是富人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;女人给别人睡的是穷人，睡别人女人的是富人。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;贫穷与富裕的新解：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;贫穷时养猪，富裕后养狗；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;贫穷时种稻，富裕后种草；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;贫穷时想娶老婆，富裕后想找情人；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;贫穷时老婆兼秘书，富裕后秘书兼老婆。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;水调歌头：重上酒楼&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;应酬复应酬，天天忙不休。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;社交公关人情事，尽在酒里头。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;泱泱五千年，底蕴多丰厚，帝王墨客江湖汉，江山美人酒。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;改革大潮涌，迂腐全荡走，惟有美女权钱欲，兴盛遍神州。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;工厂变歌厅，书店改酒楼，失业大军数百万，桑拿歌与酒。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;上面常来人，视察加旅游，小心陪侍别出错，工作有成就。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;世事多变幻，官场巧运筹，相互照应方便多，公酒交私友 。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;人生苦且短，工作多烦忧，哥们姐们再进一杯酒，泡完脚再走。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;&lt;b&gt;这年头，到处都是错别字：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;植树造零；白收起家；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;勤捞致富；择油录取；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;得财兼币；检查宴收；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;大力支吃；为民储害；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;font-size:100%;" &gt;提钱释放；攻官小姐。&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7590784012493838015?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7590784012493838015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7590784012493838015' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7590784012493838015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7590784012493838015'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/03/wwwpopyardorg.html' title='[摘自www.popyard.org] 国家机密文件：最新流行官场口诀'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1484699568065944104</id><published>2007-03-14T14:23:00.000Z</published><updated>2007-03-14T14:30:47.574Z</updated><title type='text'>今日菜根谭</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.ecs.soton.ac.uk/%7Ewf/quote/caigentan/cover.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px;" src="http://www.ecs.soton.ac.uk/%7Ewf/quote/caigentan/cover.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I created a news feeder (RSS), quote of the day from Chinese wisdom: Vegetable Root (菜根谭）, which can be added into Google personal homepage.&lt;br /&gt;&lt;a href="http://fusion.google.com/add?feedurl=http%3A//www.ecs.soton.ac.uk/%7Ewf/quote/caigentan/rss.xml"&gt;&lt;img src="http://buttons.googlesyndication.com/fusion/add.gif" alt="Add to Google" border="0" height="17" width="104" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1484699568065944104?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1484699568065944104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1484699568065944104'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2007/03/blog-post.html' title='今日菜根谭'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7412206914447934367</id><published>2006-12-15T22:46:00.000Z</published><updated>2006-12-15T23:04:15.175Z</updated><title type='text'>Use Numbers</title><content type='html'>To argue, try to use statements with numbers, like&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"1000 sites * 20 services * 200 VOs * 10 roles/groups = 40M metadata"&lt;/li&gt;&lt;li&gt;"100k CPUs * 10 jobs per day * 10 queries per job = 10M queries per day, 115 queries per second."&lt;/li&gt;&lt;li&gt; Publishing one service adds 138 RDF statements to the triple store, which consumes up about 25 KB of memory. Then each triple uses 181 bytes. Each metadata has at least 3 triples: (entity, hasMetadata, metadata), (metadata, hasMetadataType, type), (metadata, hasMetadataValue, value). Thus 4M metadata uses 181 * 3 * 4M = 2.1GB.&lt;/li&gt;&lt;/ul&gt;And pay attention to detail.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7412206914447934367?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7412206914447934367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7412206914447934367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7412206914447934367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7412206914447934367'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/use-number.html' title='Use Numbers'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5646395692502486929</id><published>2006-12-06T23:34:00.000Z</published><updated>2006-12-06T23:36:01.211Z</updated><title type='text'>似曾相识：雨中的苏州</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T3RexjHEbhs/RXdT2j8GrTI/AAAAAAAAACU/P9ywOZi5L-4/s1600-h/315152186_0b802774bc.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_T3RexjHEbhs/RXdT2j8GrTI/AAAAAAAAACU/P9ywOZi5L-4/s400/315152186_0b802774bc.jpg" alt="" id="BLOGGER_PHOTO_ID_5005561707670973746" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5646395692502486929?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5646395692502486929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5646395692502486929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5646395692502486929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5646395692502486929'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/blog-post.html' title='似曾相识：雨中的苏州'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T3RexjHEbhs/RXdT2j8GrTI/AAAAAAAAACU/P9ywOZi5L-4/s72-c/315152186_0b802774bc.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1181748564729949484</id><published>2006-12-05T22:48:00.000Z</published><updated>2006-12-05T23:10:29.130Z</updated><title type='text'>Create A User Community to Improve Our Open Source Software</title><content type='html'>Why?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create impact. &lt;a href="http://en.wikipedia.org/wiki/Open_source"&gt;Open source&lt;/a&gt; software's value relies on its usage.&lt;/li&gt;&lt;li&gt;Get feedback, which could be good ideas for the future work.&lt;/li&gt;&lt;/ul&gt;How?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a well organized website, easy downloads, a bugzilla system, etc. &lt;a href="http://twiki.grimoires.org/bin/view/Grimoires/"&gt;Twiki&lt;/a&gt; and &lt;a href="https://sourceforge.net/projects/grimoires"&gt;Sourceforge&lt;/a&gt; are very helpful in this sense.&lt;/li&gt;&lt;li&gt;Well answer questions by email.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a user list, which includes the project name, url, contacts, etc.&lt;/li&gt;&lt;/ul&gt;BTW, check out &lt;a href="http://alfredo.octavio.net/soft_drink_formula.pdf"&gt;OpenCola&lt;/a&gt;, which applies the open source idea in making cola.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1181748564729949484?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1181748564729949484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1181748564729949484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1181748564729949484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1181748564729949484'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/create-user-community-to-improve-our.html' title='Create A User Community to Improve Our Open Source Software'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8487645855599674159</id><published>2006-12-04T22:29:00.000Z</published><updated>2006-12-04T22:36:02.093Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='News'/><title type='text'>My New Laptop</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T3RexjHEbhs/RXShfrwCnlI/AAAAAAAAACI/imgNBcQo9eo/s1600-h/myVaio.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_T3RexjHEbhs/RXShfrwCnlI/AAAAAAAAACI/imgNBcQo9eo/s400/myVaio.jpg" alt="" id="BLOGGER_PHOTO_ID_5004802651607703122" border="0" /&gt;&lt;/a&gt;Today I got a new laptop, &lt;a href="http://uk.insight.com/apps/productpresentation/index.php?product_id=SOYASZ3XWP&amp;nbs_search=lang%3Den-gb%26C%3D102%26S%3D1015%26K%3D%264220v%3DCore%2B2%2BDuo%264515v%3D2%264203v%3D2%2BGB%26M%3DSO"&gt;a SONY VAIO&lt;/a&gt;, which has&lt;br /&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;li&gt;Intel® Core™ 2 Duo T7200 Processor 2.0GHz&lt;/li&gt;&lt;li&gt;2GB, 100GB HDD &amp;amp; DVD/RW Super Multi DL Drive&lt;/li&gt;&lt;li&gt;13.3" WXGA TFT Display, Bluetooth &amp; FREE T-Mobile WAN Card&lt;/li&gt;&lt;li&gt;... ...&lt;/li&gt;&lt;li&gt;And a fingerprint reader! So that I am able to log in Windows by using my fingerprint. Cool!       &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8487645855599674159?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8487645855599674159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8487645855599674159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8487645855599674159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8487645855599674159'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/my-new-laptop.html' title='My New Laptop'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T3RexjHEbhs/RXShfrwCnlI/AAAAAAAAACI/imgNBcQo9eo/s72-c/myVaio.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6741959562144636159</id><published>2006-12-03T18:38:00.000Z</published><updated>2006-12-03T19:00:30.666Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='News'/><category scheme='http://www.blogger.com/atom/ns#' term='Thought'/><title type='text'>学什么专业？挣多少钱？——美国各级毕业生2006薪水调查</title><content type='html'>摘自&lt;a href="http://www.popyard.com/cgi-mod/newspage.cgi?num=73334&amp;r=0&amp;amp;v=0"&gt;&lt;span style=";font-size:100%;color:gray;"  &gt;八阕&lt;/span&gt;&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;&lt;copiedcontent&gt;&amp;lt;CopiedContent&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;八阕】美国大学与雇主协会，每年按4个季度分别发布新毕业的大学生、 硕士和博士研究生的薪水调查报告，这报告共涉及80个学士专业，40个硕士专业，23个博士专业。冬、春、夏三季发布的数据是各季度的数据，秋季版发布的 是去年8月31日到今年9月1日为止的整个学年数据。以下列出的是该协会最新公布的美国博士和硕士毕业生2006年秋季薪水调查报告。&lt;/span&gt;&lt;/copiedcontent&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;b&gt;美国博士毕业生2006年薪水最高的几种专业：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;1、商业管理(Business Administration/Management)：$81,438&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;2、电气/电子与通信工程(Electrical/Electronics &amp; Communications Engineering)： $81,297&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;3、冶金工程(含陶瓷科学与工程)(Metallurgical Engineering )：$80,667&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;4、计算机科学(Computer Sciences)：$76,630&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;5、化学工程(Chemical Engineering)：$75,659&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;6、计算机工程(Computer Engineering)：$74,750&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;7、工业/制造工程(Industrial/Manufacturing Engineering)：$73,292&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;8、物理(Physics)：$72,357&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;如果这些工程师没有升迁到高层管理，做到退休一般年薪不会超过$150,000&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;b&gt;美国博士毕业生2006年薪水最低的几种专业：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;1、心理学(Psychology)：$49,374&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;2、人文科学(Humanities)：$48,938&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;3、社会科学(Social Sciences)：$48,487&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;4、生物/生命科学(Biological Sciences/Life Sciences)：$43,916&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;5、英语语言与文学(English Language &amp;amp; Literature/Letters )：$41,405&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;b&gt;美国硕士毕业生2006年薪水最高的10种专业：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;01、计算机科学(Computer Sciences)：$71,165&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;02、石油工程(Petroleum Engineering)：$68,833&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;03、电气/电子与通信工程(Electrical/Electronics &amp; Communications Engineering)：$66,687&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;04、计算机工程(Computer Engineering)：$66,545&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;05、地质及相关科学(Geological &amp;amp; Related Sciences)：$64,111&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;06、材料科学(Materials Sciences)：$63,500&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;07、航天/航空/宇航工程(Aerospace/Aeronautical/Astronautical Engineering)：$62,811&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;08、工业/制造工程(Industrial/Manufacturing Engineering )：$61,273&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;09、机械工程(Mechanical Engineering)：$61,234&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;10、化学工程(Chemical Engineering)：$59,008&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;如果这些工程师没有升迁到高层管理，做到退休一般年薪不会超过$120,000&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;b&gt;2004年美国律师的年薪平均为：$94,930&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;最低年薪：$64,620，最高年薪： $143,620&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;在公司和企业管理层谋职(Management of companies and enterprises)：$126,250 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;在联邦政府谋职(Federal Government)：$108,090 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;在法律机构谋职(Legal services)：$99,580 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;在地方政府谋职(Local government)：$73,410 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;在州政府谋职(State government)：$70,280 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;2004年美国各科医生的年薪：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;麻醉科(Anesthesiology)：$306,964 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;外科、普通外科(Surgery, general)：$255,438 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;妇产科(Obstetrics/Gynecology：$233,061 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;内科(Internal medicine)：$155,530 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;小儿/青少年科(Pediatrics/Adolescent medicine)：$152,690 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;精神科(Psychiatry)：$163,144 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;家庭全科(Family Practice)：$150,267 &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;b&gt;联邦人口普查局2006年11月还发表了一项调查数据“2004年美国学历与平均年薪”：&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;高中以下学历平均年薪：$19,169&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;高中毕业平均年薪：　　$28,645&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;大学毕业平均年薪：　　$51,554&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;硕士以上学位平均年薪：$78,093&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;从以上各项的调查报告看来，华人根深蒂固的教育观念“学好数理化，走遍天下都不怕”，似乎真的放之四海而皆准了。并且，华人父母努力说服自己的子女当律师和医生也是有根有据的。当然，学历越高收入越多的说法更是真理。&lt;/span&gt;&lt;/p&gt;&amp;lt;/CopiedContent&amp;gt;&lt;br /&gt;&lt;br /&gt;我的评论：&lt;br /&gt;&lt;ul&gt;&lt;li&gt;选择专业前先要做好各个专业的benchmark, 什么专业工资最高。看来benchmark真是无时无地不重要。&lt;/li&gt;&lt;li&gt;计算机科学博士起薪只比计算机科学硕士高7.7%。虽然理论上博士比硕士有更好的成长空间，究竟读不读博士还是要慎重考虑。&lt;/li&gt;&lt;li&gt;医生收入压倒性的高，远高于其他专业，甚至包括律师。还是学医收入高。&lt;/li&gt;&lt;li&gt;读书有用啊。读书越多，收入越高。&lt;/li&gt;&lt;/ul&gt;BTW, I read this from Ian Foster's blog:&lt;br /&gt;&lt;br /&gt;"&lt;em&gt;Indeed, it was outsiders—those with expertise at the periphery of a problem's field—who were most likely to find answers and do so quickly&lt;/em&gt;."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6741959562144636159?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6741959562144636159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6741959562144636159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6741959562144636159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6741959562144636159'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/2006.html' title='学什么专业？挣多少钱？——美国各级毕业生2006薪水调查'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8243654394932589539</id><published>2006-12-01T21:45:00.000Z</published><updated>2006-12-01T22:10:17.820Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><title type='text'>Java I/O</title><content type='html'>&lt;a href="http://developers.sun.com/learning/javaoneonline/2005/coreplatform/TS-4141.html"&gt;This presentation&lt;/a&gt; gives a good overview of Java I/O, from which I have learned:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;FileInputStream/FileOutputStream: for sequential I/O and simple to buffer&lt;/li&gt;&lt;li&gt;RandomAccessFile: for full random-access&lt;/li&gt;&lt;li&gt;FileChannel: adds support for NIO byte buffers&lt;/li&gt;&lt;li&gt;MappedByteBuffer: for memory-mapped I/O&lt;/li&gt;&lt;li&gt;Buffering: for instance, use BufferedOutputStream for buffering FileOutputstream&lt;/li&gt;&lt;li&gt;Forcing I/O, e.g. flush() or FileChannel.force(), equals to the "fsync" system call&lt;br /&gt;&lt;/li&gt;&lt;li&gt;No direct I/O in Java&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8243654394932589539?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8243654394932589539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8243654394932589539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8243654394932589539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8243654394932589539'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/12/java-io.html' title='Java I/O'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-7232375287929982100</id><published>2006-11-30T22:06:00.000Z</published><updated>2006-11-30T22:53:49.763Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><category scheme='http://www.blogger.com/atom/ns#' term='Thought'/><title type='text'>Google File System</title><content type='html'>&lt;span style=""&gt; The &lt;a href="http://labs.google.com/papers/gfs.html"&gt;Google File System&lt;/a&gt; is a scalable distributed file system for large distributed data-intensive applications, being used within Google. &lt;/span&gt;The paper, published in the &lt;span style=""&gt;   19&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;th&lt;/span&gt; &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;ACM&lt;/span&gt; Symposium on Operating Systems Principles, is a well written computer engineering paper. System builders should read it.&lt;br /&gt;&lt;br /&gt;Quoted from its conclusion:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-size:100%;"&gt;"We started by reexamining traditional file system assumptions in light of our current and anticipated application workloads and technological environment. Our observations have led to radically different points in the design space. We treat component failures as the norm rather than the exception, optimize for huge files that are mostly appended to (perhaps concurrently) and then read (usually sequentially), and both extend and relax the standard file system interface to improve the overall system."&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Lesson learnt:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;Application driven.&lt;/li&gt;&lt;li&gt;Base on the technological environment. Base on the facts of performance characteristics. Performance benchmark is the foundation for system design.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Application/file system (or OS, or underlying infrastructure, etc.) co-design.&lt;/li&gt;&lt;li&gt;Optimize for what should be optimized.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=""&gt;&lt;span style="font-style: italic;"&gt;"Our system provides fault tolerance ..."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lesson learnt:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;Reliability is a must for any system. System must work. Never forget reliability, persistence, fault tolerance during system design.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;"... This makes possible a simple, centralized master that does not become a bottleneck. ..."&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Lesson learnt:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;Down to earth.&lt;/li&gt;&lt;li&gt;&lt;em&gt;...I had already come to the conclusion             that in the practise of computing, where we have so much latitude           for making a mess of it, mathematical elegance is not a dispensible           luxury,             but a matter of life and death. - &lt;i&gt;Edsger Wybe Dijkstra ["My           hopes of computing science" (EWD 709)]&lt;/i&gt;&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;em style="font-style: italic;"&gt;&lt;/em&gt;&lt;span style="font-style: italic;"&gt;        elegant: [...]ingeniously simple and effective. - Concise           Oxford Dictionary&lt;br /&gt;&lt;/span&gt;         &lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;This elegance makes perfect sense in the domain of system design. May we say in system design, elegance is not a dispensible luxury, but a matter of life and death.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-7232375287929982100?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/7232375287929982100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=7232375287929982100' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7232375287929982100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/7232375287929982100'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/google-file-system.html' title='Google File System'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2850129307645740044</id><published>2006-11-17T10:58:00.000Z</published><updated>2006-11-17T11:00:24.823Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Collection'/><title type='text'>A Korean Artificial Beauty</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger2/2395/4487/1600/983494/koreanbeauty.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/x/blogger2/2395/4487/400/693621/koreanbeauty.jpg" alt="" border="0" /&gt;&lt;/a&gt;A authentic dream face based on popular Korean stars.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2850129307645740044?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2850129307645740044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2850129307645740044' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2850129307645740044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2850129307645740044'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/korean-artificial-beauty.html' title='A Korean Artificial Beauty'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-2612945349813184842</id><published>2006-11-16T20:18:00.000Z</published><updated>2006-11-16T20:57:56.788Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><title type='text'>A Very Interesting Story</title><content type='html'>Copied from &lt;a href="http://ianfoster.typepad.com/"&gt;Ian Foster's blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;copiedcontent&gt;&amp;lt;CopiedContent&amp;gt;&lt;br /&gt;&lt;/copiedcontent&gt;&lt;h3 class="entry-header"&gt;Hadoop on EC2&lt;/h3&gt;                   &lt;p&gt;Here's &lt;a href="http://glinden.blogspot.com/2006/11/hadoop-on-amazon-ec2.html"&gt;something neat&lt;/a&gt; (and details &lt;a href="http://wiki.apache.org/lucene-hadoop/AmazonEC2"&gt;here&lt;/a&gt;).&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;&lt;a href="http://lucene.apache.org/hadoop/about.html"&gt;Hadoop&lt;/a&gt;, an open source clone of &lt;a href="http://labs.google.com/papers/gfs.html"&gt;Google FS&lt;/a&gt; and &lt;a href="http://labs.google.com/papers/mapreduce.html"&gt;MapReduce&lt;/a&gt;, can be run on top of &lt;a href="http://www.amazon.com/gp/browse.html?node=201590011"&gt;Amazon EC2&lt;/a&gt;, a hosting service that allows leasing servers on an hourly basis.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;As Greg Linden goes on to say:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Developers may now be able to rapidly bring up hundreds of servers, run a massive parallel computation on them using Hadoop's MapReduce implementation, and then shut down all the instances, all with low effort and at low cost. Very cool.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;My colleague Tim Freeman points out that you can run those same VMs on your own resources using the &lt;a href="http://workspace.globus.org/"&gt;Globus Workspace service&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&amp;lt;/CopiedContent&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I got a feeling that parallel computing becomes more and more available, and has better and better programmability.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-2612945349813184842?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/2612945349813184842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=2612945349813184842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2612945349813184842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/2612945349813184842'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/very-interesting-story.html' title='A Very Interesting Story'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-5323970799621621013</id><published>2006-11-16T17:17:00.001Z</published><updated>2006-11-16T23:43:40.790Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Thought'/><title type='text'>Provenance of Life</title><content type='html'>We are moving. Our current landlord claims the carpet is "new". Although it does not look like a new one at all, and I remember it was not very clean when I moved in one year ago, we do not have any evidence to support our point. The landlord also blames us that we did not report problems to them promptly. Having consulted the university accommodation officer, we now learn that we had better write to them and keep a photocopy of the letter.&lt;br /&gt;&lt;br /&gt;The evidence matters. The evidence could be pictures, receipts, letters, or anything concrete, not transient, but retrievable. Furthermore, the evidences should not be isolated. They should be logically linked together, and finally lead to some conclusion. Put it in another way, when we see an event in the life, we would like to "see" the complete process that leads to this event. By "see" we really mean to reconstruct it in a convincible way.&lt;br /&gt;&lt;br /&gt;My boss is investigating a &lt;a href="http://twiki.pasoa.ecs.soton.ac.uk/bin/view/PASOA/WebHome"&gt;"provenance"&lt;/a&gt; project, which defines "the provenance of a piece of data is the process that led to that piece of data". The aim of the project is to "to conceive a computer-based representation of provenance that allows us to perform useful analysis and reasoning ...".&lt;br /&gt;&lt;br /&gt;I argue we also need provenance support in our lives. Important facts should be documented in a retrievable and searchable way, for instance, in a computer-based way. We should keep recording provenance of life.&lt;br /&gt;&lt;br /&gt;Google advocates searching instead of organizing. Ideally, as long as we record the provenance of life in our computer or on the internet, there should be a way to query and retrieve it.&lt;br /&gt;&lt;br /&gt;I am interested in all techniques to improve productivity. It is great that some software could help to record the provenance of life an query over it, which will definitely improve our productivity of life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-5323970799621621013?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/5323970799621621013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=5323970799621621013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5323970799621621013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/5323970799621621013'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/provenance-of-life.html' title='Provenance of Life'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-6437708037777466651</id><published>2006-11-11T11:01:00.000Z</published><updated>2006-11-11T21:23:19.872Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Collection'/><title type='text'>来点喜气与财气</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/7081/351388375303501/1600/becomerich.0.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: center; cursor: pointer; width: 320px;" src="http://photos1.blogger.com/blogger2/7081/351388375303501/1600/becomerich.0.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;拷贝自&lt;a href="http://www.edubridge.com/index.html"&gt;二闲堂&lt;/a&gt;.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/7081/351388375303501/1600/becomerich.0.jpg"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-6437708037777466651?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/6437708037777466651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=6437708037777466651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6437708037777466651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/6437708037777466651'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/blog-post_11.html' title='来点喜气与财气'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8739182755020907273</id><published>2006-11-08T10:11:00.000Z</published><updated>2006-11-10T23:23:40.193Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><title type='text'>The Outcome of MPT</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/2395/4487/1600/throughput.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger2/2395/4487/320/throughput.jpg" alt="" border="0" /&gt;&lt;/a&gt;Here is a visualized outcome of &lt;a href="http://runtime32.blogspot.com/2006/10/massive-parallel-test-kit.html"&gt;MPT&lt;/a&gt;. The x-axis is the number of processors used in the throuthput test (1 - 32). The y-axis is the number of threads per processor (1 - 16). The z-axis is the measured throughput. More precisely, it is the number of service discovery (by name) requests served in 30 minutes when there are 5000 service descriptions registered in GRIMOIRES. When 32 processors and 16  threads per processor are used, GRIMOIRES can serve 62,877 service discovery requests in 30 minutes , i.e., 34.9 per second. Each request costs 28.6 milliseconds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8739182755020907273?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8739182755020907273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8739182755020907273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8739182755020907273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8739182755020907273'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/outcome-of-mpt.html' title='The Outcome of MPT'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-4490297923707400626</id><published>2006-11-07T14:17:00.000Z</published><updated>2006-11-11T21:26:23.512Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Travel'/><title type='text'>旅游大计</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/2395/4487/1600/impressionism.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger2/2395/4487/320/impressionism.jpg" alt="" border="0" /&gt;&lt;/a&gt;星期六一早起床, 阳光明媚, 万物复苏. 乘机定下今后N年的旅游大计. 以求心中有数, 目标明确.&lt;br /&gt;&lt;br /&gt;这里我来谈三点.&lt;br /&gt;&lt;br /&gt;(一) 回顾过去, 成绩很大.&lt;br /&gt;&lt;br /&gt;香港, 东方之珠, 生活5年, 非常好;&lt;br /&gt;倫敦, 逝去帝国的首都, 非常好;&lt;br /&gt;巴黎, 文化艺术之都, 非常好;&lt;br /&gt;瑞士, 美丽的高山, 湖泊, 非常好;&lt;br /&gt;芝家哥, the mile of magnificence, 不错;&lt;br /&gt;加拿大BC, 温哥华, 维多利亚, 不错, 从温哥华到维多利亚的水路很美;&lt;br /&gt;洛山基, 听说治安很差, 硬是没敢进downtown;&lt;br /&gt;胜地呀哥, 还是不错的, 还看到了航母.&lt;br /&gt;&lt;br /&gt;(二) 面对现实, 压力很大.&lt;br /&gt;&lt;br /&gt;这里又要谈两点, 一如何在时间上创造机会, 二是如何在经济上开源节流. 以后有时间再版详细谈.&lt;br /&gt;&lt;br /&gt;(三) 展望将来, 希望很大.&lt;br /&gt;&lt;br /&gt;埃及, 非常想去看看古埃及的伟大;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;日本&lt;/span&gt;, 又爱又恨, 要去走走;&lt;br /&gt;台湾, 另类中国, 要去看看;&lt;br /&gt;纽约, 要去;&lt;br /&gt;拉丝围家四, 要去;&lt;br /&gt;欧洲, 那是要经常过去看看的, 意大利, 西班牙, 德国, 北欧, ..., 法国和瑞士也要再去;&lt;br /&gt;西藏的债也是要还的;&lt;br /&gt;非洲, 南美, 大洋洲, 有机会都要去踩上几个脚印.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-4490297923707400626?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/4490297923707400626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=4490297923707400626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4490297923707400626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/4490297923707400626'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/blog-post.html' title='旅游大计'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-1956374995580220178</id><published>2006-11-07T14:06:00.000Z</published><updated>2006-11-10T23:36:16.833Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Thought'/><title type='text'>The Reasons to Have a Blog</title><content type='html'>According to Wikipedia, the term "blog" is a contraction of "web log".  From its original name, blog can be inferred to have two characteristics that correspond to the two purposes for me to blog.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Blog is a log that is organized as a chronicle. I can use blog to track events in my life and to record  my thoughts. In this sense, the blog is just like a diary.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Blog is web based thus it is intended to be read by people. Blog can be a good communication tool to present the blogger. Blog is actually a bilateral communication tool because it allows other to comment.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-1956374995580220178?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/1956374995580220178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=1956374995580220178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1956374995580220178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/1956374995580220178'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/reasons-to-have-blog.html' title='The Reasons to Have a Blog'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-8045583829079647557</id><published>2006-11-02T20:15:00.000Z</published><updated>2006-11-10T23:39:21.847Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><category scheme='http://www.blogger.com/atom/ns#' term='Thought'/><title type='text'>Monitor the Blog and Benchmark the Program</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger2/2395/4487/1600/geo.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger2/2395/4487/320/geo.jpg" alt="" border="0" /&gt;&lt;/a&gt;I am using &lt;a href="http://www.google.com/analytics/"&gt;Google Analytics&lt;/a&gt; to monitor visits to my blog. See the picture, in which the dots indicates where somebody has visited my blog. There is even one returning visitor. Not bad!&lt;br /&gt;&lt;br /&gt;It is a good practice to start monitoring since the website is established. Just like it is a good practice to start benchmarking since the program is prototyped.&lt;br /&gt;&lt;br /&gt;Monitoring is an inherent requirement of a website. Thus it should become a part of website infrastructure. I.e., when you establish a website, your website is automatically being monitored. No webmaster effort is involved.&lt;br /&gt;&lt;br /&gt;Just like benchmarking is an inherent requirement of a program. Benchmarking should become a part of development environment. When you prototype a program, it costs you zero or little effort to benchmark the program. Some benchmark specific code should be automatically added into your program. Thus according to the benchmark data, you can make a decision on whether to take a certain refactoring or not. Will &lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;Aspect-Oriented Programming&lt;/a&gt; help on this?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-8045583829079647557?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/8045583829079647557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=8045583829079647557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8045583829079647557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/8045583829079647557'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/monitor-blog-and-benchmark-program.html' title='Monitor the Blog and Benchmark the Program'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-748909899475945641</id><published>2006-11-01T20:50:00.000Z</published><updated>2006-11-10T23:42:37.817Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><title type='text'>Use VMware to Release Server-Side Software</title><content type='html'>I am using &lt;a href="http://www.vmware.com/"&gt;WMware&lt;/a&gt;'s free &lt;a href="http://www.vmware.com/products/server/"&gt;VMware Server&lt;/a&gt; to create a &lt;a href="http://sourceforge.net/projects/grimoires"&gt;GRIMOIRES&lt;/a&gt; &lt;a href="http://www.vmware.com/vmtn/appliances/"&gt;virtual appliance&lt;/a&gt;. I admit it is not very easy to install GRIMOIRES. And I believe it is not easy to install any server-side software, probably because of the tedious and error prone procedure to configure, for instance, backend database, and security.&lt;br /&gt;&lt;br /&gt;While VMware is able to relieve this pain. We create a VMware virtual appliance, which includes OS and our software.  Our customer  simply downloads it, and is able to play it, thus avoiding the painful installation procedure. The size of the VMware virtual appliance could be much much bigger than the size of our software. But who cares. Our computer spends more time in downloading, but we spend much less time in installation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-748909899475945641?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/748909899475945641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=748909899475945641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/748909899475945641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/748909899475945641'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/11/use-vmware-to-release-software.html' title='Use VMware to Release Server-Side Software'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-116233090070253751</id><published>2006-10-31T20:59:00.000Z</published><updated>2006-11-10T23:45:37.920Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Technology'/><title type='text'>Massive Parallel Test Kit</title><content type='html'>I have implemented a Massive Parallel Test Kit (MPT) whose major goal is to measure the throughput of a server. While in my case, MPT is used to measure the throughput of our web service registry, &lt;a href="http://sourceforge.net/projects/grimoires"&gt;GRIMOIRES&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;MPT has the following features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;MPT is an &lt;a href="http://www-unix.mcs.anl.gov/mpi/"&gt;MPI&lt;/a&gt; program. So it is able to create a large number of real parallel clients on a computer cluster to generate a large number of requests simultaneously.  That is why it is claimed to be "massive parallel". By the way, it is really convenient to program a cluster using MPI.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Each MPI process invokes a Java program, ThroughputTest.  ThroughputTest provides basic functionalities required to run a throughput test. Above all, it supports user provided plug-in, called Worker, which implements the actual test business logic.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In fact, Worker extends Thread. Thus two forms of parallelism are leveraged in MPT: multi-processing at the MPI level, and multi-threading in at the Java level.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;MPT has a single control point. The degree of multi-processing, the degree of multi-threading, and the test time are all set as the parameters for the MPI program. The latter two are then passed as environment variables to ThrouputTest. &lt;/li&gt;&lt;li&gt;The fairness of the service can be revealed by calculating the deviation of the throughputs measured by individual MPI processes.&lt;/li&gt;&lt;/ul&gt;I believe MPT is a useful tool to conduct a stress test for web services. A cluster is useful for a building and testing environment for web services. After more tests of MPT, I will release it at the GRIMOIRES project website.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-116233090070253751?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/116233090070253751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=116233090070253751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116233090070253751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116233090070253751'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/10/massive-parallel-test-kit.html' title='Massive Parallel Test Kit'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-116222746695853138</id><published>2006-10-30T16:55:00.000Z</published><updated>2006-11-10T23:51:29.053Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Collection'/><title type='text'>传说中在大陆花10万元拍的婚纱照</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bbs.gdzjtour.com/attachments/forumid_8/06_MDhMCY5zbPs6.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://bbs.gdzjtour.com/attachments/forumid_8/06_MDhMCY5zbPs6.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;a href="http://www.popyard.com/cgi-mod/npost.cgi?num=117345&amp;amp;r=0"&gt;More photos&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-116222746695853138?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/116222746695853138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=116222746695853138' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116222746695853138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116222746695853138'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/10/10.html' title='传说中在大陆花10万元拍的婚纱照'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-116216767390129627</id><published>2006-10-30T00:04:00.000Z</published><updated>2006-11-10T23:47:25.758Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Life'/><title type='text'>Many First Times Today</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/4715/700/1600/itchen.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/4715/700/320/itchen.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Happy today! Lovely weather. We had many first times today.  For the first time, we had our Hong Kong style dim sum in UK. It is not bad. For the first time, we drove through a bridge asking for a payment, 50p. There is a good view along the bridge and nice drive.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-116216767390129627?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/116216767390129627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=116216767390129627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116216767390129627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116216767390129627'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/10/many-first-times-today.html' title='Many First Times Today'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36759899.post-116206814415836720</id><published>2006-10-28T21:38:00.000+01:00</published><updated>2006-10-31T21:48:27.290Z</updated><title type='text'>My Very First Blog</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/4715/700/1600/checkOK.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/4715/700/320/checkOK.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This is my first blog.&lt;br /&gt;&lt;br /&gt;Testing&lt;br /&gt;&lt;br /&gt;测试&lt;br /&gt;&lt;br /&gt;Keep testing&lt;br /&gt;&lt;br /&gt;继续测试&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36759899-116206814415836720?l=runtime32.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://runtime32.blogspot.com/feeds/116206814415836720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36759899&amp;postID=116206814415836720' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116206814415836720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36759899/posts/default/116206814415836720'/><link rel='alternate' type='text/html' href='http://runtime32.blogspot.com/2006/10/my-very-first-blog.html' title='My Very First Blog'/><author><name>Weijian Fang</name><uri>http://www.blogger.com/profile/05551545798752711948</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://photos1.blogger.com/blogger/4715/700/1600/face.jpg'/></author><thr:total>0</thr:total></entry></feed>
