I am looking for some feedback any may have on this:
Let's say I've mounted a package "com.company.package" using
PackageRequestTargetUrlCodingStrategy
on "/foo." So I have several pages, /foo/Bar, /foo/Baz, etc. Now, I want my
page mounts to be case-insensitive in the case that a user has caps lock on
or types in all lower case or whatever. For
PackageRequestTargetUrlCodingStrategy this works for the "/foo" part, but
not the classname part, obviously.

So I implemented a CaseInsensitiveClassResolver that delegates to a
DefaultClassResolver. In the case that the DefaultClassResolver cannot find
the class, the CaseInsensitiveClassResolver tries to load the class by
trying different combinations of upper/lower case in the classname. So, for
"bar" it would try to resolve "com.company.package.Bar," "
com.company.package.bAr," "com.company.package.baR," etc, obviously finding
"com.company.package.Bar" and returning that class.

This works pretty well. Now, obviously it's not the most efficient thing,
possibly having to catch several
ClassNotFoundException/NoClassDefFoundError exceptions
before finding the class (assuming the name exists and is spelled correctly,
just with wrong case). But it might be better than returning a 404 on a page
simply due to improper case. I wouldn't expect it to happen often, as more
often than not the user will probably use a link the get to the pages, and
so no typing at all. But in the rare case...

So, any thoughts?

Here's the code:

public class CaseInsensitiveClassResolver implements IClassResolver {

private static final Logger logger =
LoggerFactory.getLogger(CaseInsensitiveClassResolver.class);
 private DefaultClassResolver resolver = new DefaultClassResolver();
 public Iterator<URL> getResources(String name) {
return resolver.getResources(name);
}

public Class<?> resolveClass(String classname) {
Class<?> clazz = null;
try {
clazz = resolver.resolveClass(classname);
} catch (ClassNotFoundException e1) {
clazz = resolveClassCaseInsensitive(classname);
} catch (NoClassDefFoundError e2) {
clazz = resolveClassCaseInsensitive(classname);
}
return clazz;
}
 public Class<?> resolveClassCaseInsensitive(String classname) throws
ClassNotFoundException {
if (logger.isDebugEnabled()) {
logger.debug("Class not found for " + classname + ".  Trying to look up
case-insensitive.");
}
String packageName = classname.substring(0, classname.lastIndexOf('.'));
String simpleName = classname.substring(classname.lastIndexOf('.') + 1);
 String combos = capsCombinations(simpleName.toLowerCase(), 0);
Class<?> cls = null;
for (String combo : combos.split(",")) {
try {
cls = resolver.resolveClass(packageName + "." + combo);
} catch (ClassNotFoundException e1) {
if (logger.isDebugEnabled()) {
logger.debug("Class not found for " + packageName + "." + combo + ".");
}
} catch (NoClassDefFoundError e2) {
if (logger.isDebugEnabled()) {
logger.debug("Class not found for " + packageName + "." + combo + ".");
}
}
if (cls != null) {
if (logger.isDebugEnabled()) {
logger.debug("Class found for " + packageName + "." + combo + ".");
}
return cls;
}
}
return null;
}

private String capsCombinations(String word, int startIndex) {
StringBuilder sb = new StringBuilder(word);
if (word.equals(word.toUpperCase())) {
return sb.toString();
} else {
for (; startIndex < word.length();) {
char[] chars = word.toCharArray();
chars[startIndex] = Character.toUpperCase(chars[startIndex]);
sb.append(",");
sb.append(capsCombinations(new String(chars), ++startIndex));
}
return sb.toString();
}
}
}
-- 
Matthew Rollins Hanlon
http://squareoftwo.org
_____________________
Hanlon's Razor:
"Never attribute to malice that which can be adequately explained by
stupidity."
http://wikipedia.org/wiki/Hanlon's_razor

Reply via email to