Dec 29, 2010

String.trim() on Unicode space characters In Depth

As developers, we know that the \u00A0 is a unicode space character. Even the \240 is a unicode space character. As a Java developer, have you been working with String.trim()? I am sure, your answer would be "Yes"!

Now, let us come to an interesting pointer. Have you ever had a look at how String.trim() works? If you had been tech savvy and if you would have read the Java Specs, am sure, you would be knowing the bizarre nature of String class's trim() function.

For the others, let us get further. Just type in the following java code as a stand-alone Java program and try to run it!

Sample Program
public class Sample {
public static void main(String arg[])
{
    String test = "\240";
    System.out.println("hai:"+test.trim()+":hai");
    for(int i=0;i<test.length();i++)
    {
        char ch = test.charAt(i);
        System.out.println(ch+":"+Character.isSpaceChar(ch));
    }

}
Output:
hai: :hai<br />

In the above example, when you run it, you would be surprised to see that the text between "hai:" and ":hai" would still be a space even after executing trim() on the test string. As a developer, I expected "hai::hai" to be printed too! But the "hai: :hai" surprised me. On digging a bit further, I am able to see that the Java String class trim() works a bit differently.

So, I was wondering whether trim() really trims all white spaces and space characters? May be not and here goes the clarification.

Trim(): Clarification in Detail

Java's String abide by UTF-16. However, Java's trim() says that it trims off the leading and trailing white space characters listed by Java and not unicode. It does not trim all the space and (or) white space characters as defined by uni-code. In this context, we need to understand 2 more pointers.
  1. Character.isWhiteSpace(char/int): Checks whether the specified int or character is a whitespace. 'white space' here refers to a sub set of white space characters defined by unicode(excluded are the non-breaking white space characters defined by unicode and included are uni-code lower control characters that are equal or below U+0020), a list of white space characters defined by Java(not in the unicode list). 
  2. Character.isSpaceChar(char): Checks whether the given character is a space character. Space character in turn refers to space characters defined by uni-code.

And as I understand, Java String Class's trim() trims off the white spaces (list as defined by Java) and this is definitely not as intuitive as it should have been and hence this post!

As always, I appreciate your feedback/hollers regarding this article any time!

Dec 22, 2010

How To Access Spring Security Tags or JspTagLibs on Spring Secuirty in Apache Velocity?

I was working on a Spring framework based application where in I wanted to incorporate Spring Security quickly. While doing so, there was a need for me to display links in the UI based on the logged in user roles. The UI that I was using was Apache Velocity. I knew the fact that there were JSPTagLibs available for Spring Security.

I had incorporated the basic security and I was using Spring Security 3.0.4. So, I was exploring on using the Spring Security JSP tab library into the Apache Velocity Templates for displaying a few links based on the roles of the principal who had logged in! In this juncture, I wanted to use the JSPTagLibs of Spring security in the velocity template.
When I explored options on this, it was so unfortunate that I could not find any. But , when I confronted the resolved JIRA issue on 'Support for jsp taglibs in freemarker templates', initially I presumed that the same or a similar structure might be present for velocity too.
But the freemarker blog article on 'Velocity or FreeMarker: Looking at 5 Years of Practical Experience' made me realize that my presumption was wrong.

Further to this, I had to explore alternative options.

The best and the quickest alternative was to make use of a wrapper class that can get me the objects that I needed in the velocity views. For this, I needed a wrapper class for the Security tag library that can get me the objects/properties that I needed to make use of in my views. So I went ahead and made use of the following wrapper class. I had a wrapper class as shown below. This contained the properties/methods related to the security that I intended to make use of inside my velocity views.
package com.utils;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class VelocitySecUser {

/**
* Gets the user name of the user from the Authentication object
*
* @return the user name as string
*/
public static String getPrincipal() {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (obj instanceof UserDetails) {
return ((UserDetails) obj).getUsername();
} else {
return "Guest";
}
}

/**
* Is the user granted all of the grantedAuthorities passed in
*
* @param roles a string array of grantedAuth
* @return true if user has all of the listed authorities/roles, otherwise false
*/
public static boolean allGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
continue;
return false;
}
return true;
}

/**
* Is the user granted any of the grantedAuthorities passed into
*
* @param roles a string array of grantedAuth
* @return true if user has any of the listed authorities/roles, otherwise false
*/
public static boolean anyGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
return true;
}
return false;
}

/**
* is the user granted none of the supplied roles
*
* @param roles a string array of roles
* @return true only if none of listed roles are granted
*/
public static boolean noneGranted(String[] checkForAuths) {
Set<String> userAuths = getUserAuthorities();
for (String auth : checkForAuths) {
if (userAuths.contains(auth))
return false;
}
return true;
}

private static Set<String> getUserAuthorities() {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Set<String> roles = new HashSet<String>();
if (obj instanceof UserDetails) {
Collection<GrantedAuthority> gas = ((UserDetails) obj).getAuthorities();
for (GrantedAuthority ga : gas) {
roles.add(ga.getAuthority());
}
}
return roles;
}
}


Further to this, you might have to add this as a bean into the attribute map of your velocity view resolver as given below:
<br /> <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"><br />        <property name=....//><br /> <property name="attributesMap"><br />               <map><br />                <entry key="sec"><ref bean="veloSecUserDetails"/></entry><br />               </map><br /> </property>              <br /> </bean><br /> <bean id ="veloSecUserDetails" class ="com.utils.VelocitySecUser"/><br /> 
When this is done, automatically, you would have the object $sec accessible from within your velocity templates. You can start making use of this object in the velocity templates using the code shown below:
<br />Testing the Object $sec <br />Name of the principal is: ${sec.principal} <br />#if($sec.AllGranted("ROLE_USER")) <br />     The principal has USER role within the application<br />#end<br />
That is it!!Your code starts woking great and you have access to all the methods that you have it in the wrapper within your Apache velocity template on the flu!

I sincerely express my thanks to the discussion at Spring forum since the base ideas are basically discussed here as the solution for accessing spring security tags within Velocity Templates!

As usual, I look forward getting your hollers/feedback regarding this post any time!

How To Resolve 'org.springframework.core.convert.ConversionFailedException: Unable to convert value from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is java.lang.IllegalArgumentException: Left-hand side type must not be null'

I had been using Spring framework 3.0.0. I had the requirement of passing an attribute map to one of my bean in the application context and I was using the conversion service as shown in the code snippet below
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

When ever I try to set the attribute map to the bean, it was giving me the following exception
org.springframework.core.convert.ConversionFailedException: Unable to convert value {<your value>} from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is java.lang.IllegalArgumentException: Left-hand side type must not be null

The error was, of course. not helpful and did not give me any clue as to why and from where the problem emerged from. I was thinking that the objects, the key value, that I was passing was not of the expected type. However, since that was not the case, I had to explore a bit across the Internet in this regard. When I explored, I found that there is a problem with the conversionService bean in the Spring Framework version 3.0.0 that has been fixed in Spring Framework 3.0.1. This has been documented as a JIRA issue. A

As pointed out in the JIRA link, I observed that the problem was with the conversion service of the Spring version 3.0.0. Fortunately, the issue has been fixed in the 3.0.1 version itself.fter going through this, I ended up in downloading the latest Spring framework jars and the code started working like charm!

So, whenever you try to add an attribute map to any of your bean in the application context within a Spring 3.0.0 based application, and, if you are using a conversionService that references org.springframework.format.support.FormattingConversionServiceFactoryBean, and if you confront a problem like 'Unable to convert value from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is java.lang.IllegalArgumentException: Left-hand side type must not be null', then please have a look at the JIRA issue and upgrade your jars accordingly.

Since I thought that this might help a few of you who are confronting similar issues, I have documented this and posted here. I appreciate your hollers/feedback regarding this post any time!