package org.appfuse.webapp.server;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.google.web.bindery.requestfactory.server.DefaultExceptionHandler;
import com.google.web.bindery.requestfactory.server.RequestFactoryServlet;
import com.google.web.bindery.requestfactory.server.ServiceLayerDecorator;
import com.google.web.bindery.requestfactory.server.impl.FindService;
import com.google.web.bindery.requestfactory.shared.Locator;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
public class CustomRequestFactoryServlet extends RequestFactoryServlet {
private static final long serialVersionUID = -4245826401547466758L;
public CustomRequestFactoryServlet() {
super(new CustomExceptionHandler(), new ServiceLayerDecorator() {
@Override
public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
ApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(CustomRequestFactoryServlet.getThreadLocalServletContext());
return context.getBean(clazz);
}
@Override
public Object invoke(Method domainMethod, Object... args) {
if (FindService.class.equals(domainMethod.getDeclaringClass())) {
// Entities should only be accessed through secured
// RequestService methods (do not use find)
throw new AccessDeniedException("Access is disabled through FindService.find() method");
// FIXME this exception is not gracefully handled by
// CustomExceptionHandler, but at least we are safer
}
return super.invoke(domainMethod, args);
}
});
}
/**
*
*
*/
private static class CustomExceptionHandler extends DefaultExceptionHandler {
/**
*
* @see com.google.web.bindery.requestfactory.server.DefaultExceptionHandler#createServerFailure(java.lang.Throwable)
*/
@Override
public ServerFailure createServerFailure(Throwable throwable) {
try {
return createCustomServerFailure(throwable);
} catch (Exception e) {
return super.createServerFailure(throwable);
}
}
/**
*
* @param throwable
* @return
* @throws Exception
*/
private ServerFailure createCustomServerFailure(Throwable throwable) throws Exception {
if (throwable instanceof AuthenticationException) {
getServletResponse().sendError(HttpServletResponse.SC_UNAUTHORIZED);
return null;
}
if (throwable instanceof AccessDeniedException) {
if (!RequestFactoryServlet.getThreadLocalRequest().isRequestedSessionIdValid()) {
// if session has expired send a 401 error code instead of
// 403
getServletResponse().sendError(HttpServletResponse.SC_UNAUTHORIZED);
return null;
}
getServletResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
return null;
}
return super.createServerFailure(throwable);
}
private HttpServletResponse getServletResponse() {
return RequestFactoryServlet.getThreadLocalResponse();
}
}
}