Was the java.util.regex package based on Jakarta-ORO?

A lot of Java libraries that need regex functionality, but also need to retain compatability across 1.3 and earlier VMs use the famous Jakarta ORO library. This is a great (and fully-featured) regex implementation. An example of a project that uses this is one of the projects that I am a committer on, Jakarta Commons-Net. This is a very popular library which is mainly used for its FTP functionality, e.g. Ant’s FTP task uses it as its FTP engine.
However, it is designed to be compatible with 1.3 and earlier VMs. One of the implications of this is that its regex parsing is done by ORO, which necessitates extra “baggage” in the form of a separate jar download. As an exercise, I decided to see how easy it would be to convert the existing ORO code to a JDK-based approach. I first created a branch in SVN (here), and started to work on the ORO code.
It turned out to be trivial to make the changes, in fact the APIs were so similar I have a strong feeling that the Sun engineers who implemented the java.util.regex package may have been heavily influenced by the design of the ORO interface.
First, look at the ORO version:


private Pattern pattern = null;
    private MatchResult result = null;
    protected PatternMatcher _matcher_ = null;

    public RegexFTPFileEntryParserImpl(String regex)
    {
        super();
        try
        {
            _matcher_ = new Perl5Matcher();
            pattern   = new Perl5Compiler().compile(regex);
        }
        catch (MalformedPatternException e)
        {
            throw new IllegalArgumentException (
               "Unparseable regex supplied:  " + regex);
        }
    }

    /**
     * Convenience method delegates to the internal MatchResult's matches()
     * method.
     *
     @param s the String to be matched
     @return true if s matches this object's regular expression.
     */

    public boolean matches(String s)
    {
        this.result = null;
        if (_matcher_.matches(s.trim()this.pattern))
        {
            this.result = _matcher_.getMatch();
        }
        return null != this.result;
    }



    /**
     * Convenience method delegates to the internal MatchResult's groups()
     * method.
     *
     @return the number of groups() in the internal MatchResult.
     */

    public int getGroupCnt()
    {
        if (this.result == null)
        {
            return 0;
        }
        return this.result.groups();
    }

And now look at the equivalent Java 1.4+ version:


private Pattern pattern = null;
    private MatchResult result = null;
    protected Matcher _matcher_ = null;

    public RegexFTPFileEntryParserImpl(String regex)
    {
        super();
        try
        {
            pattern   = Pattern.compile(regex);
        }
        catch (PatternSyntaxException pse)
        {
            throw new IllegalArgumentException (
               "Unparseable regex supplied:  " + regex);
        }
    }

    /**
     * Convenience method delegates to the internal MatchResult's matches()
     * method.
     *
     @param s the String to be matched
     @return true if s matches this object's regular expression.
     */

    public boolean matches(String s)
    {
        this.result = null;
        _matcher_ = pattern.matcher(s);
        if (_matcher_.matches())
        {
            this.result = _matcher_.toMatchResult();
        }
        return null != this.result;
    }



    /**
     * Convenience method delegates to the internal MatchResult's groups()
     * method.
     *
     @return the number of groups() in the internal MatchResult.
     */

    public int getGroupCnt()
    {
        if (this.result == null)
        {
            return 0;
        }
        return this.result.groupCount();
    }

Hibernate, java.util.Date and java.sql.Date Issues

One issue that can crop up during unit testing is problems with date mapping. In SQL terms dates to a “day” level of precision can be specified using a DATE column and dates with a “time” element can be mapped using a TIMESTAMP (or MySQL DATETIME) column. These map respectively to the Java SQL types java.sql.Date and java.sql.Timestamp. Note that a java.util.Date object can specify times, up to a millisecond level of precision, whereas a java.sql.Timestamp object can handle nanosecond-level precision.

If we are using Hibernate to map a persistent class, and one of the fields is a day-level-precision Date field, we could map it like so:

In a unit test to exercise the persistence mapping, it could go something like the following:

Foo f = new Foo();
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
f.setStartDate(now);

and then test the retrieved persistent entity like so:

fooEntity = session.load(Foo.class, id);
assertEquals(f.getStartDate(), fooEntity.getStartDate());

The assertion will fail. The reason for this is that the call to fooEntity.getStartDate() returns an instance of java.sql.Date, whereas we are comparing against a java.util.Date. Since java.sql.Date is a subclass of java.util.Date, our tests will run without any ClassCastExceptions, but any equality checks will fail. The reason for this is apparent from the java.sql.Date javadoc:

To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be ‘normalized’ by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

This means that any Date objects we retrieve from our Hibernate-mapped objects will have an effective time of midnight , i.e.something like 25-Jan-2006 00:00:00. We cannot just use the getTime() method to retrieve a long equaivalent of the date value either, as the they will ave the same problem.

What we can do is “normalize” the Date object before we persist it, like so:

private Date normalize(Calendar cal) {
cal.set(Calendar.MILLISECOND, 0);
cal.set(2006,0,25,0,0,0);
return cal.getTime();
}

...
Date now = normalize(cal);
event.setStartDate(now);

Now our asserts will pass without a problem.

There’s an entertaining overview of the bigger picture here.

Implementing the Composite design pattern with Hibernate Annotations

Quite frequently when building applications, you will come across the requirement to build a hierarchical tree structure of entities, for instance, an organisational hierarchy. This is elegantly represented by the composite design pattern. A further twist on this is creating persistent trees of objects. Here I show you how to achieve this with Hibernate 3 using the annotations package.

Here is an example of the type of structure that I am trying to represent:

Composite Pattern

First, let’s define our composite class (the parent):


import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

@Entity()
@Inheritance (
strategy=InheritanceType.SINGLE_TABLE,
discriminatorType=DiscriminatorType.STRING,
discriminatorValue="0")
@DiscriminatorColumn()
public abstract class OrganisationUnit {
private Set<OrganisationUnit> children;
private OrganisationUnit parent;
private String name;
private Long id;
private Double budget;
@Transient()
public boolean isLeaf() {
return (children == null || children.size() == 0);
}
@Transient()
public boolean isRoot() {
return (parent == null);
}
@OneToMany(mappedBy="parent",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
public Set<OrganisationUnit> getChildren() {
return children;
}
public void setChildren(Set<OrganisationUnit> children) {
this.children = children;
}
@Column()
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne()
@JoinColumn()
public OrganisationUnit getParent() {
return parent;
}
public void setParent(OrganisationUnit parent) {
this.parent = parent;
}
@Id(generate=GeneratorType.AUTO)
public Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
@Column( scale=2 )
public Double getBudget() {
return budget;
}
public void setBudget(Double budget) {
this.budget = budget;
}
}


And now a leaf entity:

@Entity()
@Inheritance( discriminatorValue="C")
public class CostCentre extends OrganisationUnit {
private String costCentreId;
@Column( length=16 )
public String getCostCentreId() {
return costCentreId;
}
public void setCostCentreId(String costCentreId) {
this.costCentreId = costCentreId;
}
}

And another leaf-level entity:

import javax.persistence.Entity;
import javax.persistence.Inheritance;
@Entity()
@Inheritance(discriminatorValue="B")
public class BusinessArea extends OrganisationUnit {
}

And now a test case, which we can use to build up a (small, in this case) test tree of objects:

import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;

public class TestOrganisationUnitCRUD extends PersistentTestCase {
public void testSaveParent() {

OrganisationUnit parent = new BusinessArea();
parent.setName("Parent");
OrganisationUnit child1 = new CostCentre();
child1.setName("Cost Centre 1");
child1.setParent(parent);
OrganisationUnit child2 = new CostCentre();
child2.setName("Cost Centre 2");
child2.setParent(parent);
// Add the children to the set
Set<OrganisationUnit> children = new HashSet<OrganisationUnit>();
children.add(child1);
children.add(child2);
parent.setChildren(children);
// Persist the children
Session session = sessionFactory.getCurrentSession();
Long id = (Long) session.save(parent);
session.flush();
session.evict(parent);
session.evict(child1);
session.evict(child2);
OrganisationUnit entity = (OrganisationUnit) session.load(BusinessArea.class, id);
assertNotNull(entity);
assertEquals(entity.getName(), parent.getName());
assertNotNull(entity.getChildren());
assertEquals(entity.getChildren().size(), 2);
for (OrganisationUnit child: entity.getChildren()) {
assertEquals(child.getClass(), CostCentre.class);
}
}
}

In this case, PersistentTestCase is just a convenience class that extends JUnit’s TestCase class and adds support for the Open Session In View functionality provided by Spring.

Acegi Security and NTLM

(UPDATE: there is a more up-to-date Spring Security example here: http://blog.mediasoft.be/?p=1).

In the tradition of the NTLM-related posts that I have previously written (see here, here, here, here and here), I have a final installment concerning how to get NTLM authentication to work with Acegi Security. Acegi has provisional support for NTLM authentication (currently the support is not bundled with the distribution, it’s in CVS only), and there is an open ticket here tracking the progress of that feature. Hopefully it will be bundled with 1.0, but for now, you can just download the CVS source tree and build it. The underlying NTLM support is built on top of JCIFS, which I have written about previously.

Once you have downloaded and built Acegi with NTLM support, you need to set up your application context. First, we add the NTLM filter and an entry point:

< bean id="ntlmEntryPoint" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilterEntryPoint"/>

< bean id="ntlmFilter" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter">
<
property name="defaultDomain">< value>MYDOMAIN
<
property name="domainController" value="10.0.1.2"/>
<
property name="authenticationManager" ref="authenticationManager"/>
<
property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>< /bean>

Next, we add a SecurityEnforcementFilter and pass it the entry point:

< bean id="securityEnforcementFilter" class="org.acegisecurity.intercept.web.SecurityEnforcementFilter">
<
property name="filterSecurityInterceptor">
<
ref bean="filterInvocationInterceptor"/>
<
property name="authenticationEntryPoint">
<
ref bean="ntlmEntryPoint"/>

Our filterSecurityInterceptor can be defined as follows:

<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=ROLE_ADMIN
</value>
</property>
</bean>

We referenced an authorisationManager in the above snippet, which we define as follows:


<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<bean id="smbAuthenticationProvider"
class="org.acegisecurity.providers.smb.SmbNtlmAuthenticationProvider">
<property name="authorizationProvider">
<ref local="daoAuthenticationProvider"/>
</property>
</bean>
</list>
</property>
</bean>

The SmbNtlmAuthenticationProvider above implements the authenticate() method, which will be used to verify the user’s credentials. Note that we have a reference to a daoAuthenticationProvider, which we define as follows:

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.NullPasswordDaoAuthenticationProvider">

I will explain why we are using a custom provider later.

Now that we have defined a protected resource, we need to provide an authorisation store. For this simple example, I will use an InMemoryDaoImpl. Note that you probably wouldn’t do this in real life – I haven’t even bothered to specify a passwordEncoder here.

<bean id="memoryAuthenticationDao" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userMap">
<value>
jsmith=PASSWORD,ROLE_ADMIN
</value>
</property>
</bean>

We also need to specify an access decision mechanism. In this case we will just use the vanilla unanimous voting mechanism. Read the Acegi docs for more details on this procedure. For now, we just need to know that it’s there.


<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter"/>


<bean id="accessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">
<property name="allowIfAllAbstainDecisions">
<value>false</value>
</property>
<property name="decisionVoters">
<list>
<ref local="roleVoter"/>
</list>
</property>
</bean>

Now we can define the filter chain. In the application’s web.xml, we create the following entry:

<filter>
<filter-name>Acegi HTTP Request Security Filter</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Acegi HTTP Request Security Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

We are going to use Spring’s “virtual filter chain” here. We thus define the order of the filters in Spring’s application context:


<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,ntlmFilter,securityEnforcementFilter
</value>
</property>
</bean>

The order of entries is important here. Our httpSessionContextIntegrationFilter is defined as:


<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="context" value="org.acegisecurity.context.SecurityContextImpl"/>
</bean>

Normally, this should be all there is to it. There are actually a couple of extra steps I needed to complete in order to get this to work, however:

  • Refactor NtlmAuthenticationToken to extend UsernamePasswordAuthenticationToken.
  • Implement the NullPasswordDaoAuthenticationProvider. I just copied the code for the existing DaoAuthenticationProvider and removed any logic in the additionalAuthenticationChecks() method. The reason for doing this is that by default, DaoAuthenticationProvider calls authentication.getCredentials(), which returns null in our case.

Some of these changes may be due to the manner in which I implemented the demo (i.e using an InMemoryDaoImpl itself, and not broader issues. There dies seem to be a lot of configuration required, however once it is written, it works a treat. After having worked on an inhouse security framework in the past, I have vowed to to look at Acegi first from now on whenever this requirement arises in the future.

Now Running WordPress 2.0

I just performed an upgrade to WordPress 2.0 and it went smoothly. It only took about 10 minutes, and the new version looks excellent. I have tried other blogging tools in the past (notably JRoller and Movable Type), but WordPress beats them both hands down. The new Ajax features, JavaScript UI effects, and enhanced rich content editors are great.