/**
* 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.tide.seam21;
import static org.jboss.seam.annotations.Install.FRAMEWORK;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.granite.tide.seam.AbstractSeamServiceContext;
import org.granite.tide.seam.TideInvocation;
import org.granite.tide.seam.async.AsyncContext;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.async.AbstractDispatcher;
import org.jboss.seam.async.Dispatcher;
import org.jboss.seam.async.Schedule;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.Log;
/**
* TideEvents override to intercept Seam events handling
*
* @author William DRAI
*/
@Name("org.jboss.seam.core.events")
@Install(precedence=FRAMEWORK+1)
@Scope(ScopeType.STATELESS)
@BypassInterceptors
@AutoCreate
public class TideEvents extends Events {
protected @Logger Log log;
protected static final String ASYNC_EVENT = "org.granite.tide.seam.AsyncEvent";
@Override
public void raiseEvent(String type, Object... parameters) {
if (ASYNC_EVENT.equals(type)) {
TideInvocation.init();
AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, true);
WrappedEvent event = (WrappedEvent)parameters[0];
serviceContext.setAsyncContext(event.getAsyncContext()); // Reset context
raiseEvent(event.getType(), event.getParams());
// Send event through Gravity only
serviceContext.sendEvent(null, null);
}
else {
super.raiseEvent(type, parameters);
// Ignore built-in Seam events to avoid stack overflow in component initialization
if (!type.startsWith("org.jboss.seam.pre") && !type.startsWith("org.jboss.seam.post")) {
// Event should be always handled if we want to allow to send them through Gravity
AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false);
if (serviceContext != null) // ServiceContext is null during Seam initialization
serviceContext.raiseEvent(type, parameters);
}
}
}
@Override
public void raiseAsynchronousEvent(String type, Object... parameters) {
AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false);
String sessionId = serviceContext != null ? serviceContext.getSessionId() : null;
if (serviceContext != null && sessionId != null)
super.raiseAsynchronousEvent(ASYNC_EVENT, new WrappedEvent(serviceContext.getAsyncContext(), type, parameters));
else
super.raiseAsynchronousEvent(type, parameters);
}
// Seam 2.1
private static final Class<?>[] SEAM21_TIMED_EVENT_ARGS = new Class<?>[] { String.class, Schedule.class, Object[].class };
@SuppressWarnings("all")
public void raiseTimedEvent(String type, Schedule schedule, Object... parameters) {
AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false);
String sessionId = serviceContext != null ? serviceContext.getSessionId() : null;
Dispatcher dispatcher = AbstractDispatcher.instance();
if (dispatcher != null) {
try {
Method m = dispatcher.getClass().getMethod("scheduleTimedEvent", SEAM21_TIMED_EVENT_ARGS);
if (serviceContext != null && sessionId != null)
m.invoke(dispatcher, ASYNC_EVENT, schedule, new Object[] { new WrappedEvent(serviceContext.getAsyncContext(), type, parameters) });
else
m.invoke(dispatcher, type, schedule, parameters);
}
catch (Exception e) {
log.error("Could not raise timed event", e);
}
}
}
protected static class WrappedEvent implements Serializable {
private static final long serialVersionUID = 1L;
private AsyncContext asyncContext;
private String type;
private Object[] params;
public WrappedEvent(AsyncContext asyncContext, String type, Object[] params) {
this.asyncContext = asyncContext;
this.type = type;
this.params = params;
}
public AsyncContext getAsyncContext() {
return asyncContext;
}
public String getType() {
return type;
}
public Object[] getParams() {
return params;
}
}
}