package org.itsnat.droid.impl.browser.serveritsnat; import android.os.AsyncTask; import org.itsnat.droid.ClientErrorMode; import org.itsnat.droid.HttpRequestResult; import org.itsnat.droid.ItsNatDroidException; import org.itsnat.droid.ItsNatDroidServerResponseException; import org.itsnat.droid.OnEventErrorListener; import org.itsnat.droid.impl.browser.HttpRequestData; import org.itsnat.droid.impl.browser.HttpRequestResultOKImpl; import org.itsnat.droid.impl.browser.HttpUtil; import org.itsnat.droid.impl.browser.PageImpl; import org.itsnat.droid.impl.browser.serveritsnat.event.EventGenericImpl; import org.itsnat.droid.impl.dom.DOMAttrRemote; import org.itsnat.droid.impl.dom.ParsedResource; import org.itsnat.droid.impl.dom.layout.XMLDOMLayoutPageItsNat; import org.itsnat.droid.impl.domparser.XMLDOMParserContext; import org.itsnat.droid.impl.util.MimeUtil; import org.itsnat.droid.impl.util.NameValue; import java.net.SocketTimeoutException; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Created by jmarranz on 10/07/14. */ public class EventSender { protected EventManager evtManager; public EventSender(EventManager evtManager) { this.evtManager = evtManager; } public EventManager getEventManager() { return evtManager; } public ItsNatDocItsNatImpl getItsNatDocItsNatImpl() { return evtManager.getItsNatDocItsNatImpl(); } public void requestSync(EventGenericImpl evt, String servletPath, List<NameValue> paramList, HttpRequestData httpRequestData, Map<String,ParsedResource> urlResDownloadedMap,XMLDOMParserContext xmlDOMParserContext) { HttpRequestResultOKBeanshellImpl result = null; try { result = executeInBackground(this, servletPath, httpRequestData, paramList,urlResDownloadedMap,xmlDOMParserContext); } catch (Exception ex) { onFinishError(this, ex, evt); return; // No podemos continuar } onFinishOk(this, evt, result); } public void requestAsync(EventGenericImpl evt, String servletPath, List<NameValue> paramList, HttpRequestData httpRequestData, Map<String,ParsedResource> urlResDownloadedMap,XMLDOMParserContext xmlDOMParserContext) { HttpPostEventAsyncTask task = new HttpPostEventAsyncTask(this, evt, servletPath, paramList, httpRequestData,urlResDownloadedMap,xmlDOMParserContext); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); // Con execute() a secas se ejecuta en un "pool" de un sólo hilo sin verdadero paralelismo } public static HttpRequestResultOKBeanshellImpl executeInBackground(EventSender eventSender, String servletPath, HttpRequestData httpRequestData, List<NameValue> paramList, Map<String,ParsedResource> urlResDownloadedMap,XMLDOMParserContext xmlDOMParserContext) throws Exception { // Ejecutado en multihilo en el caso async HttpRequestResultOKImpl result = HttpUtil.httpPost(servletPath, httpRequestData, paramList, null); if (!(result instanceof HttpRequestResultOKBeanshellImpl)) throw new ItsNatDroidServerResponseException("Expected " + MimeUtil.MIME_BEANSHELL + " MIME in Content-Type:" + result.getMimeType(),result); HttpRequestResultOKBeanshellImpl resultBS = (HttpRequestResultOKBeanshellImpl)result; // No veo problemas de multithread en estas 4 líneas de código: PageItsNatImpl pageItsNat = eventSender.getItsNatDocItsNatImpl().getPageItsNatImpl(); String pageURLBase = pageItsNat.getPageURLBase(); XMLDOMLayoutPageItsNat xmlDOMLayoutPage = pageItsNat.getInflatedXMLLayoutPageItsNatImpl().getXMLDOMLayoutPageItsNat(); String itsNatServerVersion = pageItsNat.getItsNatServerVersion(); String code = resultBS.getResponseText(); XMLDOMLayoutPageItsNatDownloader downloader = XMLDOMLayoutPageItsNatDownloader.createXMLDOMLayoutPageItsNatDownloader(xmlDOMLayoutPage,pageURLBase, httpRequestData,itsNatServerVersion,urlResDownloadedMap,xmlDOMParserContext); LinkedList<DOMAttrRemote> attrRemoteListBSParsed = downloader.parseBeanShellAndDownloadRemoteResources(code); if (attrRemoteListBSParsed != null) resultBS.setAttrRemoteListBSParsed(attrRemoteListBSParsed); return resultBS; } public static void onFinishOk(EventSender eventSender, EventGenericImpl evt, HttpRequestResultOKBeanshellImpl result) { try { eventSender.processResult(evt, result, true); } catch (Exception ex) { PageImpl page = eventSender.getEventManager().getItsNatDocItsNatImpl().getPageImpl(); OnEventErrorListener errorListener = page.getOnEventErrorListener(); if (errorListener != null) { HttpRequestResult resultError = (ex instanceof ItsNatDroidServerResponseException) ? ((ItsNatDroidServerResponseException) ex).getHttpRequestResult() : result; errorListener.onError(page, evt, ex, resultError); } else { if (ex instanceof ItsNatDroidException) throw (ItsNatDroidException) ex; else throw new ItsNatDroidException(ex); } } } public static void onFinishError(EventSender eventSender, Exception ex, EventGenericImpl evt) { HttpRequestResult result = (ex instanceof ItsNatDroidServerResponseException) ? ((ItsNatDroidServerResponseException) ex).getHttpRequestResult() : null; ItsNatDroidException exFinal = eventSender.convertExceptionAndFireEventMonitors(evt, ex); PageImpl page = eventSender.getEventManager().getItsNatDocItsNatImpl().getPageImpl(); OnEventErrorListener errorListener = page.getOnEventErrorListener(); if (errorListener != null) { errorListener.onError(page, evt, exFinal, result); } else { int errorMode = eventSender.getItsNatDocItsNatImpl().getClientErrorMode(); if (errorMode != ClientErrorMode.NOT_CATCH_ERRORS) { // Error del servidor, lo normal es que haya lanzado una excepción ItsNatDocItsNatImpl itsNatDoc = eventSender.getItsNatDocItsNatImpl(); itsNatDoc.showErrorMessage(true, result, exFinal, errorMode); } else throw exFinal; } } public void processResult(EventGenericImpl evt,HttpRequestResultOKBeanshellImpl result,boolean async) { ItsNatDocItsNatImpl itsNatDoc = getItsNatDocItsNatImpl(); itsNatDoc.fireEventMonitors(false,false,evt); String responseText = result.getResponseText(); itsNatDoc.evalEventResultScript(responseText, evt, result.getAttrRemoteListBSParsed()); if (async) evtManager.returnedEvent(evt); } public ItsNatDroidException convertExceptionAndFireEventMonitors(EventGenericImpl evt, Exception ex) { ItsNatDocItsNatImpl itsNatDoc = getItsNatDocItsNatImpl(); if (ex instanceof ItsNatDroidException && ex.getCause() instanceof SocketTimeoutException) { // Esperamos este error en el caso de timeout y lo tratamos de forma singular en fireEventMonitors (el segundo param a true) itsNatDoc.fireEventMonitors(false, true, evt); } else { itsNatDoc.fireEventMonitors(false, false, evt); } if (ex instanceof ItsNatDroidException) return (ItsNatDroidException)ex; else return new ItsNatDroidException(ex); } }