Bash Keyboard Shortcuts – Programming Function Keys

I often backup a file by adding time stamp to the file using command like the one below:

mv catalina.out catalina.out.`date +%F-%I%M%p`

Date command “date +%F-%I%M%p” generates time stamp in the format YYYY-MM-DD-HHMM(AM/PM) (e.g. 2011-01-06-0729PM). Instead of typing the full date command, function keys F1, F2, etc. (not sure what other keys can be programmed) can be set to print it on command line when pressed. This post describes how to program F2 key so that when pressed:

  • deletes a character (backspace)
    • Tab completion adds a space after the filename. This is to delete the space character.
  • prints .`date +%F-%I%M%p` on the command line
Bash Keyboard Shortcut
Before Pressing F2
Bash Keyboard Shortcut
After Pressing F2

Steps:

  1. Open file “.inputrc” in user home directory (vi ~/.inputrc)
  2. Type the following characters (without + sign and spaces):  ” + ctrl-v + F2″
    • double quote
    • while holding the control key press v (similar to holding shift key to type letters in caps)
    • press F2
    • double quote
  3. Type colon
  4. Type the following characters (without + sign and spaces): ” + ctrl-v + ctrl-h + .`date +%F-%I%M%p` + ”
    • double quote
    • while holding the control key press v
    • while holding the control key press h — ctrl-h is for deleting a character (ctrl-h works at command prompt also)
    • .`date +%F-%I%M%p`
    • double quote

The lines should now appear as in the picture below:

Bash Keyboard Shortcut
Entry in .inputrc

Open a new bash shell and pressing F2 should now output .`date +%F-%I%M%p`

Garbage Collectors in the J2SE 5.0 HotSpot JVM

Below is the summary on different garbage collectors prepared while reading Memory Management in the Java HotSpot™ Virtual Machine whitepaper. Hope you find it useful!

Garbage Collectors Summary: Serial, Parallel, Parallel Compacting and Concurrent Mark-Sweep (CMS)

Notable points in Concurrent Mark-Sweep Collector:

  • Also known as low-latency collector as it minimizes pause times
  • Some phases are executed concurrently with the application
  • Only garbage collector that does not perform compaction of old generation after major collection
  • Because no compaction is performed, extra heap sizes may be required
  • Has an option of running in Incremental Mode (–XX:+CMSIncrementalMode): in this mode concurrent phases are done incrementally (useful when running on machines with fewer processors to yield back processing to the application)

Related links:

How to Configure Connection Pool Using OracleDataSourceFactory in Tomcat?

Below is a sample configuration of a connection pool using OracleDataSourceFactory:

<Resource auth="Container"
name="jdbc/testDS"
type="oracle.jdbc.pool.OracleDataSource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(LOAD_BALANCE=yes)(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XXXX)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=180)(DELAY=5))))"
user="username"
password="password"
connectionCachingEnabled="true"
connectionCacheName="testCache"
connectionCacheProperties="{MinLimit=20,InitialLimit=20,MaxLimit=20,AbandonedConnectionTimeout=900}"
/>

Some points to note:

  • Attribute factory is set to oracle.jdbc.pool.OracleDataSourceFactory. If the factory attribute is not specified, connection pool will be configured using default commons DBCP BasicDataSourceFactory
    factory="oracle.jdbc.pool.OracleDataSourceFactory"
    
  • user name is set using attribute “user“.
    user="username"
    

    User name for connection pool using BasicDataSourceFactory is specified using attribute username. Why the difference? It is because the attribute user or username is not Tomcat’s resource element specific attribute, but rather the attribute specific to the factory. The factory could be written to look for user name in an attribute of its choice. For example, the factory could be written to look for user name in attribute “dbuser”. OracleDataSourceFactory looks for username in the attributes user, userName (note the capital N) and u. Below is the screenshot of code in OracleDataSourceFactory class decompiled using Java Decompiler

    Oracle Connection Pool Username

How to extract difference between two files?

Say that you have two files file1.txt and file2.txt as shown below:

file1.txt file2.txt
satish
devarapalli
java
linux
memory
slf4j
osgi
tomcat
apache
axis2
satish
apache
slf4j
osgi
java
linux
axis2
tomcat

Using commands sort and comm, we can identify the lines that are common in both files, lines unique in file1 and lines unique in file2. Below are the steps:

  1. Command comm works on sorted files, so the first step is to sort both file1.txt and file2.txt
    • sort file1.txt > file1_sorted.txt
    • sort file2.txt > file2_sorted.txt
  2. Find lines common to both files
    • comm -12 file1_sorted.txt file2_sorted.txt  | nl
      • Option “-12” means suppress unique lines in first (file1_sorted.txt) and second (file2_sorted.txt) files.
      • “| nl” — add line numbers to output
  3. Find lines unique in file2_sorted.txt
    • comm -13 file1_sorted.txt file2_sorted.txt  | nl
      • Option “-13” means suppress unique lines in first (file1_sorted.txt) file and lines common in both the files (3 – lines common in both files)
  4. Find lines unique in file1_sorted.txt
    • comm -23 file1_sorted.txt file2_sorted.txt  | nl
      • Option “-23” means suppress unique lines in second (file2_sorted.txt) file and lines common in both the files (3 – lines common in both files

How does XML Parser locate DTD?

Below is an example first line written in JSP Tag Library Descriptor (TLD):

<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "web-jsptaglib_1_1.dtd">

Note that the declaration doesn’t have the full path to the DTD like “http://abc.com/xyz/web-jsptaglib_1_1.dtd&#8221;. So, how does the XML parser locate the DTD? Even if the full URI is specified, does the parser fetch the DTD from the web server always?

Short Answer:
XML Parser resolves public identifier “-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN” to resource javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd. This DTD is loaded from jsp-api.jar.

Long Answer:
Doctype declaration format:
<!DOCTYPE rootElementName PUBLIC “publicIdentifier” “systemIdentifier”>

For the DOCTYPE declaration in TLD:

  • rootElementName=taglib
  • publicIdentifier=”-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN”
  • systemIdentifier=”web-jsptaglib_1_1.dtd”
  • Public identifier “-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN” is registered with the resource URL “/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd” using EntityResolver (SchemaResolver implements EntityResolver) in DigesterFactory.java in catalina.jar.

  • From javadoc of method org.apache.commons.digester.Digester#register():

    Digester contains an internal EntityResolver implementation. This maps PUBLICID’s to URLs (from which the resource will be loaded). A common use case for this method is to register local URLs (possibly computed at runtime by a classloader) for DTDs. This allows the performance advantage of using a local version without having to ensure every SYSTEM URI on every processed xml document is local. This implementation provides only basic functionality. If more sophisticated features are required, using setEntityResolver(org.xml.sax.EntityResolver) to set a custom resolver is recommended.

  • XMLReader is set with this entity resolver in Digester.java in tomcat-coyote.jar
  • XMLReader will resolve the registered public identifiers to resource URIs using the entity resolver

Related Links:

Relative URI “web-jsptaglib_1_2.dtd”; can not be resolved without a base URI

I noticed the error below in Tomcat logs while looking for some information — application was working normally even with this error. Another instance of Tomcat (same version – 6.0.16) that has the same web application didn’t have this error in the logs.

ERROR [main] (Digester.java:1555) - Parse Fatal Error at line 2 column -1: Relative URI "web-jsptaglib_1_2.dtd"; can not be resolved without a base URI.
org.xml.sax.SAXParseException: Relative URI "web-jsptaglib_1_2.dtd"; can not be resolved without a base URI.
        at org.apache.crimson.parser.Parser2.fatal(Parser2.java:3182)
        at org.apache.crimson.parser.Parser2.fatal(Parser2.java:3176)
        at org.apache.crimson.parser.Parser2.resolveURI(Parser2.java:2758)
        at org.apache.crimson.parser.Parser2.maybeExternalID(Parser2.java:2730)
        at org.apache.crimson.parser.Parser2.maybeDoctypeDecl(Parser2.java:1129)
        at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:489)
        at org.apache.crimson.parser.Parser2.parse(Parser2.java:305)
        at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:442)
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1644)
        at org.apache.catalina.startup.TldConfig.tldScanStream(TldConfig.java:518)
        at org.apache.catalina.startup.TldConfig.tldScanTld(TldConfig.java:555)
        at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:295)
        at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4441)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4248)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)

Though the application was working, I wondered if any JSP custom tags were not working as expected; some of the custom tags were non-ui related so it will not be obvious to end users when some tags don’t work the way they should. Below are the findings I made while debugging this issue:

  1. Crimson parser was used to parse the tld
    at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:442)
    
  2. The web application that I deployed didn’t have any crimson related jars. I verified that crimson related jars are not in TOMCAT_HOME/lib as well. Puzzled, I ran “findjars crimson” in TOMCAT_HOME and found another web app deployed on the same Tomcat has a jar having crimson parser classes and file META-INF/services/javax.xml.parsers.SAXParserFactory with value “org.apache.crimson.jaxp.SAXParserFactoryImpl”.
  3. Javadoc for method SAXParserFactory#newInstance() has details on how a SAXParserFactory implementation is chosen. From javadoc:

    Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file META-INF/services/javax.xml.parsers.SAXParserFactory in jars available to the runtime.

  4. Crimson parser from jar in another web application (say webapp1) was used to parse tld in the webapp (say webapp2) I deployed. Per Tomcat’s class loader documentation jars/classes in one webapp are not visible to another webapps deployed on the same Tomcat. So I suspected this to be a bug in Tomcat.
  5. I looked into Tomcat’s source code to see if I could spot the bug in code. I noticed getParser() method in Digester.java in tomcat-coyote.jar is checking if the parser is not null.

    Looking at the source code I guessed if Tomcat deploys webapp1 first, xml parser in Digester will be set to crimson parser and when webapp2 is deployed the parser variable will not be null so crimson parser will be used for webapp2 as well. But this didn’t sound right because a jar in one webapp is deciding what parser to use for processing tlds in another (possible all other) webapp.
  6. I found Bug 29936 – XML parser loading problems by container and it seemed like related to the problem I am having. This bug fix was included in Tomcat 6.0.18, so I deployed the web applications in Tomcat 6.0.18 and I didn’t see the error message in log file!
  7. From Comment 8:

    A possible solution is to load the (default) parser into the Digester prior to
    having it being loaded by the WebappClassloader. Since this appears to be
    one-time settable, it will use this parser regardless of what the webapp has.

    I was really interested in seeing the code changes made as part of this bug, but I couldn’t find a link or documentation that details what code changes were made. After trying out a few things I found the changes here. (See this post to know how I found this link.)

So, upgrading to Tomcat 6.0.18 would fix the XML parser issue. I am still not clear if the application should work as expected even with the error we are seeing in log file on 6.0.16 — need to find that out!