package org.esmerilprogramming.overtown.server.handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import org.esmerilprogramming.overtown.annotation.Page;
import org.esmerilprogramming.overtown.http.*;
import org.esmerilprogramming.overtown.http.converter.GenericConverter;
import org.esmerilprogramming.overtown.http.converter.ParameterConverter;
import org.esmerilprogramming.overtown.http.converter.ParametersConverter;
import org.esmerilprogramming.overtown.server.injection.CoreClassInjector;
import org.esmerilprogramming.overtown.server.injection.CoreClassInjectorImpl;
import org.esmerilprogramming.overtown.server.mounters.ConverterMounterImpl;
import org.jboss.logging.Logger;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
/**
* Created by efraimgentil<efraimgentil@gmail.com> on 28/01/15.
*/
public class MainHttpHandler implements HttpHandler {
private final Logger LOGGER;
private Class<?> controller;
private Method method;
private final String[] parameterNames;
private Set<Method> beforeTranslationMethods;
private Map<String, GenericConverter<?>> converterMap;
private Map<String, ParameterConverter> paramConverterMap;
private String responseTemplate;
private boolean isJsonResponse;
private HttpHandler internalErrorHandler;
public MainHttpHandler(ControllerMapping controller , PathMapping pathMapping, String[] parameterNames){
this.controller = controller.getControllerClass();
this.internalErrorHandler = controller.getInternalErrorHandler();
this.beforeTranslationMethods = controller.getBeforeTranslationMethods();
this.method = pathMapping.getMethod();
this.responseTemplate = pathMapping.getTemplate();
this.parameterNames = parameterNames;
this.isJsonResponse = pathMapping.isJsonResponse();
this.converterMap = new ConverterMounterImpl().mountParameterConveters(method, parameterNames);
this.paramConverterMap = new ParameterConverterMounter().identifyParametersTranslators(parameterNames, method.getParameterTypes());
LOGGER = Logger.getLogger(this.controller);
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
Object newInstance = controller.getConstructor().newInstance();
OvertownRequest request = null;
try {
Class<?>[] parameterTypes = method.getParameterTypes();
request = new OvertownRequest(exchange);
for (Method method : beforeTranslationMethods) {
method.invoke(newInstance, request);
}
request.addConverters(converterMap);
ParametersConverter translator = new ParametersConverter(paramConverterMap);
Object[] parameters =
translator.translateParameters(parameterNames, parameterTypes, request);
CoreClassInjector injector = new CoreClassInjectorImpl();
parameters = injector.injectCoreInstances(parameterNames, parameters, parameterTypes, request);
method.invoke(newInstance, parameters);
finishResponse( request );
} catch (Exception e) {
if( request != null){
try {
if (internalErrorHandler != null) {
exchange.putAttachment( request.EXCEPTION_ATTACHMENT_KEY , e);
internalErrorHandler.handleRequest(exchange);
}else{
defaultErrorHandler(e, request);
}
}catch(Exception ex) {
LOGGER.error("Your custom internal error handler throw a exception: " + ex.getMessage());
defaultErrorHandler(ex, request);
}
}else{
e.printStackTrace();
}
}
}
protected void defaultErrorHandler(Exception e , OvertownRequest request){
request.addAttribute( ErrorHandler.ERROR_500 , e );
new DefaultInternalErrorPage().handleError(request);
}
public void finishResponse(OvertownRequest request){
if(isJsonResponse){
request.respondAsJson();
}
Response response = request.getResponse();
if (!Page.NO_TEMPLATE.equals(responseTemplate) && !response.isResponseSend()) {
request.respondAsHttp();
request.addAttribute("request" , request );
request.addAttribute("contextPath" , request.getExchange().getResolvedPath() );
((HttpResponse) request.getResponse()).fowardTo(responseTemplate);
} else {
if (!response.isResponseSend()) {
response.finishResponse();
}
}
}
}