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