001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * *** 008 * 009 * Community License: GPL 3.0 010 * 011 * This file is free software: you can redistribute it and/or modify 012 * it under the terms of the GNU General Public License as published 013 * by the Free Software Foundation, either version 3 of the License, 014 * or (at your option) any later version. 015 * 016 * This file is distributed in the hope that it will be useful, but 017 * WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU General Public License for more details. 020 * 021 * You should have received a copy of the GNU General Public License 022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 023 * 024 * *** 025 * 026 * Available Commercial License: GraniteDS SLA 1.0 027 * 028 * This is the appropriate option if you are creating proprietary 029 * applications and you are not prepared to distribute and share the 030 * source code of your application under the GPL v3 license. 031 * 032 * Please visit http://www.granitedataservices.com/license for more 033 * details. 034 */ 035package org.granite.client.tide.impl; 036 037import java.util.Map; 038 039import org.granite.client.messaging.events.FaultEvent; 040import org.granite.client.messaging.messages.responses.FaultMessage; 041import org.granite.client.tide.Context; 042import org.granite.client.tide.server.ComponentListener; 043import org.granite.client.tide.server.ExceptionHandler; 044import org.granite.client.tide.server.Fault; 045import org.granite.client.tide.server.ServerSession; 046import org.granite.client.tide.server.TideFaultEvent; 047import org.granite.client.tide.server.TideResponder; 048import org.granite.logging.Logger; 049 050/** 051 * Implementation of fault handler 052 * 053 * @author William DRAI 054 */ 055public class IssueHandler<T> implements Runnable { 056 057 private static final Logger log = Logger.getLogger(IssueHandler.class); 058 059 private final ServerSession serverSession; 060 private final Context sourceContext; 061 @SuppressWarnings("unused") 062 private final String componentName; 063 @SuppressWarnings("unused") 064 private final String operation; 065 private final FaultEvent event; 066 @SuppressWarnings("unused") 067 private final Object info; 068 private final TideResponder<T> tideResponder; 069 private final ComponentListener<T> componentResponder; 070 private boolean executed = false; 071 072 073 public IssueHandler(ServerSession serverSession, Context sourceContext, String componentName, String operation, FaultEvent event, Object info, 074 TideResponder<T> tideResponder, ComponentListener<T> componentResponder) { 075 this.serverSession = serverSession; 076 this.sourceContext = sourceContext; 077 this.componentName = componentName; 078 this.operation = operation; 079 this.event = event; 080 this.info = info; 081 this.tideResponder = tideResponder; 082 this.componentResponder = componentResponder; 083 } 084 085 public void run() { 086 if (executed) 087 return; 088 executed = true; 089 090 log.error("fault %s", event.toString()); 091 092 // TODO: conversation contexts 093// var sessionId:String = faultEvent.message.headers[Tide.SESSION_ID_TAG]; 094// var conversationId:String = null; 095// if (faultEvent.message.headers[Tide.IS_LONG_RUNNING_CONVERSATION_TAG]) 096// conversationId = faultEvent.message.headers[Tide.CONVERSATION_TAG]; 097// var wasConversationCreated:Boolean = faultEvent.message.headers[Tide.WAS_LONG_RUNNING_CONVERSATION_CREATED_TAG] != null; 098// var wasConversationEnded:Boolean = faultEvent.message.headers[Tide.WAS_LONG_RUNNING_CONVERSATION_ENDED_TAG] != null; 099// 100// var context:Context = _contextManager.retrieveContext(sourceContext, conversationId, wasConversationCreated, wasConversationEnded); 101 102 Context context = sourceContext.getContextManager().retrieveContext(sourceContext, null, false, false); 103 104 FaultMessage emsg = event.getMessage(); 105 FaultMessage m = emsg; 106 Map<String, Object> extendedData = emsg != null ? emsg.getExtended() : null; 107 do { 108 if (m != null && m.getCode() != null && m.isSecurityFault()) { 109 emsg = m; 110 extendedData = emsg != null ? emsg.getExtended() : null; 111 break; 112 } 113 // TODO: check WTF we should do here 114 if (m != null && m.getCause() instanceof FaultEvent) 115 m = (FaultMessage)((FaultEvent)m.getCause()).getCause(); 116 else if (m.getCause() instanceof FaultMessage) 117 m = (FaultMessage)m.getCause(); 118 else 119 m = null; 120 } 121 while (m != null); 122 123 serverSession.onFaultEvent(event, emsg); 124 125 handleIssue(context, emsg); 126 127 boolean handled = false; 128 Fault fault = new Fault(emsg.getCode(), emsg.getDescription(), emsg.getDetails()); 129 fault.setContent(event.getMessage()); 130 fault.setCause(event.getCause()); 131 132 TideFaultEvent faultEvent = new TideFaultEvent(context, serverSession, componentResponder, fault, extendedData); 133 if (tideResponder != null) { 134 tideResponder.fault(faultEvent); 135 if (faultEvent.isDefaultPrevented()) 136 handled = true; 137 } 138 139 if (!handled) { 140 ExceptionHandler[] exceptionHandlers = context.getContextManager().getContext(null).allByType(ExceptionHandler.class); 141 if (exceptionHandlers != null && emsg != null) { 142 // Lookup for a suitable exception handler 143 for (ExceptionHandler handler : exceptionHandlers) { 144 if (handler.accepts(emsg)) { 145 handler.handle(context, emsg, faultEvent); 146 handled = true; 147 break; 148 } 149 } 150 if (!handled) 151 log.error("Unhandled fault: " + emsg.getCode() + ": " + emsg.getDescription()); 152 } 153 else if (exceptionHandlers != null && exceptionHandlers.length > 0) { 154 // Handle fault with default exception handler 155 exceptionHandlers[0].handle(context, event.getMessage(), faultEvent); 156 } 157 else { 158 log.error("Unknown fault: " + event.toString()); 159 } 160 } 161 162 if (!handled && !serverSession.isLogoutInProgress()) 163 context.getEventBus().raiseEvent(context, ServerSession.CONTEXT_FAULT, event.getMessage()); 164 165 serverSession.tryLogout(); 166 } 167 168 public void handleIssue(Context context, FaultMessage emsg) { 169 } 170}