001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2014 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.tide.seam21; 023 024import static org.jboss.seam.annotations.Install.FRAMEWORK; 025 026import java.io.Serializable; 027import java.lang.reflect.Method; 028 029import org.granite.tide.seam.AbstractSeamServiceContext; 030import org.granite.tide.seam.TideInvocation; 031import org.granite.tide.seam.async.AsyncContext; 032import org.jboss.seam.Component; 033import org.jboss.seam.ScopeType; 034import org.jboss.seam.annotations.AutoCreate; 035import org.jboss.seam.annotations.Install; 036import org.jboss.seam.annotations.Logger; 037import org.jboss.seam.annotations.Name; 038import org.jboss.seam.annotations.Scope; 039import org.jboss.seam.annotations.intercept.BypassInterceptors; 040import org.jboss.seam.async.AbstractDispatcher; 041import org.jboss.seam.async.Dispatcher; 042import org.jboss.seam.async.Schedule; 043import org.jboss.seam.core.Events; 044import org.jboss.seam.log.Log; 045 046 047/** 048 * TideEvents override to intercept Seam events handling 049 * 050 * @author William DRAI 051 */ 052@Name("org.jboss.seam.core.events") 053@Install(precedence=FRAMEWORK+1) 054@Scope(ScopeType.STATELESS) 055@BypassInterceptors 056@AutoCreate 057public class TideEvents extends Events { 058 059 protected @Logger Log log; 060 061 protected static final String ASYNC_EVENT = "org.granite.tide.seam.AsyncEvent"; 062 063 064 @Override 065 public void raiseEvent(String type, Object... parameters) { 066 if (ASYNC_EVENT.equals(type)) { 067 TideInvocation.init(); 068 AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, true); 069 070 WrappedEvent event = (WrappedEvent)parameters[0]; 071 serviceContext.setAsyncContext(event.getAsyncContext()); // Reset context 072 073 raiseEvent(event.getType(), event.getParams()); 074 075 // Send event through Gravity only 076 serviceContext.sendEvent(null, null); 077 } 078 else { 079 super.raiseEvent(type, parameters); 080 081 // Ignore built-in Seam events to avoid stack overflow in component initialization 082 if (!type.startsWith("org.jboss.seam.pre") && !type.startsWith("org.jboss.seam.post")) { 083 // Event should be always handled if we want to allow to send them through Gravity 084 AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false); 085 if (serviceContext != null) // ServiceContext is null during Seam initialization 086 serviceContext.raiseEvent(type, parameters); 087 } 088 } 089 } 090 091 092 @Override 093 public void raiseAsynchronousEvent(String type, Object... parameters) { 094 AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false); 095 String sessionId = serviceContext != null ? serviceContext.getSessionId() : null; 096 if (serviceContext != null && sessionId != null) 097 super.raiseAsynchronousEvent(ASYNC_EVENT, new WrappedEvent(serviceContext.getAsyncContext(), type, parameters)); 098 else 099 super.raiseAsynchronousEvent(type, parameters); 100 } 101 102 103 // Seam 2.1 104 private static final Class<?>[] SEAM21_TIMED_EVENT_ARGS = new Class<?>[] { String.class, Schedule.class, Object[].class }; 105 106 @SuppressWarnings("all") 107 public void raiseTimedEvent(String type, Schedule schedule, Object... parameters) { 108 AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false); 109 110 String sessionId = serviceContext != null ? serviceContext.getSessionId() : null; 111 Dispatcher dispatcher = AbstractDispatcher.instance(); 112 if (dispatcher != null) { 113 try { 114 Method m = dispatcher.getClass().getMethod("scheduleTimedEvent", SEAM21_TIMED_EVENT_ARGS); 115 if (serviceContext != null && sessionId != null) 116 m.invoke(dispatcher, ASYNC_EVENT, schedule, new Object[] { new WrappedEvent(serviceContext.getAsyncContext(), type, parameters) }); 117 else 118 m.invoke(dispatcher, type, schedule, parameters); 119 } 120 catch (Exception e) { 121 log.error("Could not raise timed event", e); 122 } 123 } 124 } 125 126 127 protected static class WrappedEvent implements Serializable { 128 129 private static final long serialVersionUID = 1L; 130 131 private AsyncContext asyncContext; 132 private String type; 133 private Object[] params; 134 135 public WrappedEvent(AsyncContext asyncContext, String type, Object[] params) { 136 this.asyncContext = asyncContext; 137 this.type = type; 138 this.params = params; 139 } 140 141 public AsyncContext getAsyncContext() { 142 return asyncContext; 143 } 144 145 public String getType() { 146 return type; 147 } 148 149 public Object[] getParams() { 150 return params; 151 } 152 } 153}