Jeff Kunkle

XML
20070330 Friday March 30, 2007
Update Mac OSX split for Pieces Larger than 2GB and Greater

Split is a very useful command-line utility for breaking large files into smaller pieces. Unfortunately, the version Apple ships with OSX 10.4 cannot split files into pieces 2GB or larger. Luckily, there is a newer version of split that you can compile and use instead of the Apple-supplied one.

There is a nice article/post over at macosxhints.com describing how to upgrade split. It's really not very hard but I thought I'd write a script so people could upgrade with a minimum of effort.

The short script is shown below. Please note that it is currently hard-coded for version 1.21 of split. You may want to check and see if there is a newer version before running the script.

#!/bin/bash
curl -o split.c "http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/usr.bin/split/split.c?rev=1.21&content-type=text/plain"
perl -p -i -e 's/#include <sys\/cdefs.h>/#include <sys\/stat.h>\n#include <sys\/cdefs.h>/' split.c
cc -Os -o split split.c
sudo mv /usr/bin/split /usr/bin/split.apple
sudo cp split /usr/bin/split
sudo chmod ugo-w /usr/bin/split
sudo chmod ugo+rx /usr/bin/split
sudo chown root:wheel /usr/bin/split
echo "Upgrade Complete."
Posted by jkunkle Mar 30 2007, 10:26:23 AM EST
20070324 Saturday March 24, 2007
Logging into Mac OS X Hidden Administrator Accounts

Every once in a while I need to login to a hidden administrator account on my Mac. It's a simple process after you invest lots of time trying to remember the key combination needed to expose the User Name and Password prompt instead of the usual graphical user account login prompt (which doesn't show the hidden admin accounts of course). Many times I've searched all over the Internet to uncover the secret and never seem to find anything quickly, so I thought I'd document it here for future reference.

Let's assume that you're staring at the usual graphical login prompt. There's a nice little picture to the left of each of your user accounts, but no way to enter a username. If you only have one user account on your Mac, you're already being prompted for the password to that account. If this is the case, hit Esc.

Now you should only see a list of all the user accounts on your Mac, and should not see a password field. Press the down arrow key until you see a gray background behind one of your user accounts. It doesn't matter which one.

Next, press Option-Enter. Your normal graphical login screen should now be replaced with two text entry fields, one for your User Name and one for your Password. Now you can enter the username and password of your hidden administrator account (or any account for that matter). That's it.

Please note that I don't know if the Option-Enter key combination does anything if you don't have any hidden accounts. You'll have to try it for yourself and see.

Posted by jkunkle Mar 24 2007, 12:20:12 PM EST
20070314 Wednesday March 14, 2007
Performance of Guarding Debug Log Statements

A few days ago, some people in the office were debating the value of our time honored tradition of guarding debug log statements. If you're not sure what I'm talking about, a short code sample should clear things up quickly.

if (log.isDebugEnabled()) {
  log.debug("Log message number " + 1);
}

It's generally accepted that guarding your log statements with an if block will improve performance if your log statements involve some kind of string concatenation, such as the example above. But what kind of performance improvement are we really talking about here?

To determine the impact of this log guarding, I wrote a simple program that repeatedly calls log statements with three different logging implementations. See attachment for the actual code.

  1. UnguardedLogger.java has no if block guarding the log statement at all.
  2. IfGuardedLogger.java has the traditional if block surrounding the log statement, just like the example above.
  3. AspectGuardedLogger.java acts just like the UnguardedLogger except that it has an AspectJ aspect guarding it's log statement. The idea here was to allow you to abandoned typing the if block guard while still enjoying its benefits.

All three implementations were asked to log one million statements in three successive batches. Each log statement included a string concatenation of six components. Each batch ran the three implementations in a different order. The results of the test run are shown below.

ImplementationTest 1Test 2Test 3
UnguardedLogger1341ms1783ms1345ms
IfGuardedLogger35ms32ms30ms
AspectGuardedLogger1343ms1612ms1364ms

Broken down by average time per log statement, that's

  • UnguardedLogger - 1.49µs/statement
  • IfGuardedLogger - 0.03µs/statement
  • AspectGuardedLogger - 1.44µs/statement

From these numbers, I've drawn two conclusions

  1. Guarding your log statements is a lot faster (in this case, 50x faster) than not guarding them at all or guarding them using an aspect. Even so, we're still down in the microsecond range here. If you're doing a lot of logging, you may notice a small improvement from guarding your log statements. Otherwise, you may not want to bother.
  2. Guarding your log statements with an around aspect is really no better than not guarding them at all. I'm not familiar with the internals of AspectJ, but my hunch is that even an around aspect will have to do the log statement string concatenation so that it could potentially be exposed as context for an advice. Hence, it ends up being about the same as not guarding the log statements at all.
Posted by jkunkle Mar 14 2007, 08:37:14 PM EST
20061129 Wednesday November 29, 2006
Start with Something New

To one extent or another, I‘ve been involved with many projects whose goal was to replace an existing system while adding some new features. On the surface, these sound like rather straightforward efforts. After all, the existing system is the source for all your legacy system replacement requirements, right? Unfortunately, these projects often struggle and many are never deployed. Why? Because they don‘t start with something new.

In my experience, legacy replacement projects first focus on supplanting the features of the old system rather than building new capabilities. In many cases, the legacy system was built over a period of years where new features were continually added and refined. However, new development efforts are rarely given years to write replacement software for the legacy system. The result is usually an initial version that doesn‘t even provide the same capabilities as the old application and adds little or nothing new. Why would a busy user spend their valuable time to learn a new system that provides less functionality than what they have today? In many cases they don‘t and the system is labeled a failure before it even gets rolling.

Why not start by building the new features first? Hook your users with new capabilities they don‘t have today and slowly replace the legacy features until the existing system is no longer needed or used. As a side benefit, your users may decide they don‘t need certain features of the legacy system anymore or that they should work differently based on their experiences with the new capabilities you‘ve given them. At the end of the day, I think you‘ll end up with a more successful application that better addresses users‘ current needs.

Posted by jkunkle Nov 29 2006, 09:25:36 PM EST
20060711 Tuesday July 11, 2006
NotNull Hibernate Annotation Validation Problems

I recently decided to try out Hibernate's annotation-based validation framework. It seems like a great solution for ensuring consistent validation of the domain model regardless of the presentation tier (web interface, web service, etc.). It very much reminds me of the declarative validation available within Rails model objects.

To make a long story short, things did not go as well as I had hoped using a Hibernate Core 3.2.0 CR2 and Hibernate Annotations 3.2.0 CR1 combination. I struggled for hours trying to figure out why I was getting a "not-null property references a null or transient value" error rather than a validation error when attempting to use the NotNull validation annotation. Eventually I discovered the problem was not that the NotNull validation wasn't working properly, but that it wasn't running at all.

In order for the annotation-based validation framework to execute, Hibernate Annotations provides a ValidatePreInsertEventListener and ValidatePreUpdateEventListener to fire the annotation validations prior to persisting any changes to the domain model. "Pre-insert" and "pre-update" events are fired after other events, in this case SaveOrUpdateEvent(s). By default, Hibernate uses the DefaultSaveOrUpdateEventListener, which is an extension of AbstractSaveEventListener. The AbstractSaveEventListener checks for null values corresponding to non-nullable database columns ( AbstractSaveEventListener:284 ) before adding the insert or update events to the execution queue( AbstractSaveEventListener:290 ) responsible for triggering pre-insert or pre-update event listeners. In case that didn't make complete sense, the bottom line is the Hibernate Core checks entities against the null constraints of the database before the annotation-based validation framework has a chance to run.

Luckily, there is a workaround, although it feels like a bit of a hack. As I mentioned previously, the DefaultSaveOrUpdateEventListener gets a chance to run before any "pre-insert" or "pre-update" events so we can use that to our advantage. The following SaveOrUpdateEventListener simply extends the Hibernate Annotations-provided ValidateEventListener and calls the validation method on "save-update" events rather than "pre-insert" and "pre-update" events.


public class ValidationEventListener 
    extends ValidateEventListener 
    implements SaveOrUpdateEventListener {

  public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException {
    final SessionImplementor source = event.getSession();
    final Object object = event.getObject();
    if (!source.getPersistenceContext().reassociateIfUninitializedProxy(object)) {
      // only validate the entity if it has been changed
      final Object entity = 
        source.getPersistenceContext().unproxyAndReassociate(object);
      super.validate(entity, event.getSession().getEntityMode());
    }
  }

}

One extemely important thing to remember when using this workaround is that you must configure the DefaultSaveOrUpdateEventListener as the second "save-update" listener (following the ValidationEventListener) or your objects will never be persisted.

Posted by jkunkle Jul 11 2006, 08:59:58 AM EDT
20060625 Sunday June 25, 2006
XSS Vulnerabilities of JSP 2.0 Expressions

&JSP 2.0 introduced a handy new capability allowing you to use JSP Expressions directly within the template text (i.e. outside of tag libraries or tag files) of a web page. This allows developers to easily expose data and objects stored in application, session, request, or page scope using a simple Ant-style syntax. It allows you to replace this


<table>
<c:forEach var="book" items="${books}">
<tr>
<td><c:out value="${book.title}"/></td>
<td><c:out value="${book.author}"/></td>
<td><c:out value="${book.isbn}"/></td>
</tr>
</c:forEach>
</table>

with this

;code>
<table>
<c:forEach var="book" items="${books}">
<tr>
<td>${book.title}</td>
<td>${book.author}</td>
<td>${book.isbn}</td>
</tr>
</c:forEach>
</table>

As you can see, the syntax in the second example is much cleaner. But, “with great power comes great responsibility.” The chink in the armor that every tutorial I‘ve read (including Sun's Java EE 5 Tutorial) fails to mention is that the expression syntax does not escape HTML characters. Therefore, any web application using JSP Expressions to output unsanitized, user-entered data will be vulnerable to Cross Site Scripting (XSS) attacks.

Unfortunately, the cure for this XSS vulnerability leads us right back to our first example. As section 2.2.2 of the JSP 2.0 Specification reads, “In cases where escaping is desired (for example, to help prevent cross-site scripting attacks), the JSTL core tag c:out can be used.”

My advice is to use JSP Expressions only as tag library attribute values and stick to using JSTL‘s c:out tag for writing text to a page. Deciding which instances of template text expression usage are safe and which are not is simply too error prone and the consequences of a mistake too dangerous.

Posted by jkunkle Jun 25 2006, 03:46:48 PM EDT