001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.messaging.service; 022 023import java.lang.reflect.Method; 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import javax.servlet.ServletException; 030 031import org.granite.config.flex.Destination; 032import org.granite.context.GraniteContext; 033import org.granite.logging.Logger; 034 035import flex.messaging.messages.Message; 036 037 038/** 039 * @author Venkat DANDA 040 * @author Cameron INGRAM 041 * 042 * Update services-config.xml to use the seam service exception handler 043 * <factory id="tideSeamFactory" class="org.granite.tide.seam.SeamServiceFactory" > 044 * <properties> 045 * <service-exception-handler>org.granite.tide.seam.SeamServiceExceptionHandler</service-exception-handler> 046 * </properties> 047 * </factory> 048 */ 049public class ExtendedServiceExceptionHandler extends DefaultServiceExceptionHandler { 050 051 private static final long serialVersionUID = -1L; 052 private static final Logger log = Logger.getLogger(ExtendedServiceExceptionHandler.class); 053 054 public static final Class<?> JAVAX_EJB_EXCEPTION; 055 static { 056 Class<?> exception = null; 057 try { 058 exception = Thread.currentThread().getContextClassLoader().loadClass("javax.ejb.EJBException"); 059 } 060 catch (Exception e) { 061 } 062 JAVAX_EJB_EXCEPTION = exception; 063 } 064 065 public ExtendedServiceExceptionHandler() { 066 this(true); 067 } 068 069 public ExtendedServiceExceptionHandler(boolean logException) { 070 super(logException); 071 } 072 073 @Override 074 protected ServiceException getServiceException(Message request, Destination destination, String method, Throwable t) { 075 if (t == null) 076 throw new NullPointerException("Parameter t cannot be null"); 077 078 Map<String, Object> extendedData = new HashMap<String, Object>(); 079 080 if (t instanceof ServiceException) { 081 ((ServiceException)t).getExtendedData().putAll(extendedData); 082 return (ServiceException)t; 083 } 084 085 List<Throwable> causes = new ArrayList<Throwable>(); 086 for (Throwable cause = t; cause != null; cause = getCause(cause)) 087 causes.add(cause); 088 089 String detail = "\n" + 090 "- destination: " + (destination != null ? destination.getId() : "") + "\n" + 091 "- method: " + method + "\n" + 092 "- exception: " + t.toString() + "\n"; 093 094 for (int i = causes.size()-1; i >= 0; i--) { 095 Throwable cause = causes.get(i); 096 for (ExceptionConverter ec : GraniteContext.getCurrentInstance().getGraniteConfig().getExceptionConverters()) { 097 if (ec.accepts(cause, t)) 098 return ec.convert(cause, detail, extendedData); 099 } 100 } 101 102 if (getLogException()) 103 log.error(t, "Could not process remoting message: %s", request); 104 105 // Default exception handler 106 ServiceException se = new ServiceException(t.getClass().getSimpleName() + ".Call.Failed", t.getMessage(), detail, t); 107 se.getExtendedData().putAll(extendedData); 108 return se; 109 } 110 111 112 public static Throwable getCause(Throwable t) { 113 Throwable cause = null; 114 try { 115 if (JAVAX_EJB_EXCEPTION != null && JAVAX_EJB_EXCEPTION.isInstance(t)) { 116 Method m = JAVAX_EJB_EXCEPTION.getMethod("getCausedByException"); 117 cause = (Throwable)m.invoke(t); 118 } 119 else if (t instanceof ServletException) 120 cause = ((ServletException)t).getRootCause(); 121 else 122 cause = t.getCause(); 123 } 124 catch (Exception x) { 125 return null; 126 } 127 return cause == t ? null : (Throwable)cause; 128 } 129}