package javango.core;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javango.api.MethodObjectParams;
import javango.api.Url;
import javango.http.HttpException;
import javango.http.HttpRequest;
import org.apache.commons.beanutils.locale.LocaleConvertUtilsBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
public class RegUrl implements Url {
private final static Log log = LogFactory.getLog(RegUrl.class);
public String pattern;
public Class<?> clazz;
public String methodName;
// cached copies of the pattern
protected Pattern p;
// cached copies of the method and parameter types
public Method method;
public Class<?>[] paramTypes;
@Inject
public RegUrl(@Assisted("pattern") String pattern, @Assisted Class<?> clazz, @Assisted("methodName") String methodName) {
super();
this.clazz = clazz;
this.methodName = methodName;
this.setPattern(pattern);
}
@Override
public String toString() {
return "Url: '" + this.pattern + "'";
}
protected void getMethodInformation(int params) {
Class<?> currentClass = this.clazz;
while(currentClass != null) {
Method[] methods = currentClass.getDeclaredMethods();
for(Method m: methods) {
if (this.methodName.equals(m.getName()) && params+1 == m.getParameterTypes().length) {
this.paramTypes = m.getParameterTypes();
this.method = m;
return;
}
}
currentClass = currentClass.getSuperclass();
}
}
public boolean matches(String url) {
return p.matcher(url).matches();
}
public MethodObjectParams getMethodObjectParams(String url, HttpRequest req) throws HttpException {
Matcher m = p.matcher(url);
if(m.matches()){
synchronized (RegUrl.class) {
if (paramTypes == null) {
getMethodInformation(m.groupCount());
if (this.method == null) {
// TODO if in debug mode show a more detailed message
// Unable to find Views.class[methodName(HttpResponse, otherparams)]
// Views contained the following methods
// ... (is it possible to show methods from a class?)
log.error("Unable to find method matching name='" + this.methodName + "' and param count = " + m.groupCount() );
throw new HttpException("Unable to find method matching name='" + this.methodName + "' and param count = " + m.groupCount() );
}
}
}
Object[] params = new Object[m.groupCount()+1];
params[0] = req;
for (int i=1;i<=m.groupCount();i++) {
LocaleConvertUtilsBean converter = new LocaleConvertUtilsBean();
params[i] = converter.convert(m.group(i), paramTypes[i]);
}
return new MethodObjectParams(this.clazz, method, params);
} else {
log.warn("Called execute on url, but pattern did not match: " + url);
return null;
}
}
protected String getPattern() {
return pattern;
}
protected void setPattern(String pattern) {
p = Pattern.compile(pattern);
this.pattern = pattern;
}
}