/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.messaging.service; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import org.granite.config.GraniteConfig; import org.granite.config.flex.Destination; import org.granite.context.GraniteContext; import org.granite.logging.Logger; import flex.messaging.messages.Message; /** * @author Venkat DANDA * @author Cameron INGRAM * * Update services-config.xml to use the seam service exception handler * <factory id="tideSeamFactory" class="org.granite.tide.seam.SeamServiceFactory" > * <properties> * <service-exception-handler>org.granite.tide.seam.SeamServiceExceptionHandler</service-exception-handler> * </properties> * </factory> */ public class ExtendedServiceExceptionHandler extends DefaultServiceExceptionHandler { private static final long serialVersionUID = -1L; private static final Logger log = Logger.getLogger(ExtendedServiceExceptionHandler.class); public static final Class<?> JAVAX_EJB_EXCEPTION; static { Class<?> exception = null; try { exception = Thread.currentThread().getContextClassLoader().loadClass("javax.ejb.EJBException"); } catch (Exception e) { } JAVAX_EJB_EXCEPTION = exception; } public ExtendedServiceExceptionHandler() { this(true); } public ExtendedServiceExceptionHandler(boolean logException) { super(logException); } @Override protected ServiceException getServiceException(Message request, Destination destination, String method, Throwable t) { if (t == null) throw new NullPointerException("Parameter t cannot be null"); Map<String, Object> extendedData = new HashMap<String, Object>(); if (t instanceof ServiceException) { ((ServiceException)t).getExtendedData().putAll(extendedData); return (ServiceException)t; } List<Throwable> causes = new ArrayList<Throwable>(); for (Throwable cause = t; cause != null; cause = getCause(cause)) causes.add(cause); String detail = "\n" + "- destination: " + (destination != null ? destination.getId() : "") + "\n" + "- method: " + method + "\n" + "- exception: " + t.toString() + "\n"; for (int i = causes.size()-1; i >= 0; i--) { Throwable cause = causes.get(i); for (ExceptionConverter ec : ((GraniteConfig)GraniteContext.getCurrentInstance().getGraniteConfig()).getExceptionConverters()) { if (ec.accepts(cause, t)) return ec.convert(cause, detail, extendedData); } } if (getLogException()) log.error(t, "Could not process remoting message: %s", request); // Default exception handler ServiceException se = new ServiceException(t.getClass().getSimpleName() + ".Call.Failed", t.getMessage(), detail, t); se.getExtendedData().putAll(extendedData); return se; } public static Throwable getCause(Throwable t) { Throwable cause = null; try { if (JAVAX_EJB_EXCEPTION != null && JAVAX_EJB_EXCEPTION.isInstance(t)) { Method m = JAVAX_EJB_EXCEPTION.getMethod("getCausedByException"); cause = (Throwable)m.invoke(t); } else if (t instanceof ServletException) cause = ((ServletException)t).getRootCause(); else cause = t.getCause(); } catch (Exception x) { return null; } return cause == t ? null : cause; } }