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 */
022 package org.granite.tide.seam21;
023
024 import static org.jboss.seam.annotations.Install.FRAMEWORK;
025
026 import java.io.Serializable;
027 import java.lang.reflect.Method;
028
029 import org.granite.tide.seam.AbstractSeamServiceContext;
030 import org.granite.tide.seam.TideInvocation;
031 import org.granite.tide.seam.async.AsyncContext;
032 import org.jboss.seam.Component;
033 import org.jboss.seam.ScopeType;
034 import org.jboss.seam.annotations.AutoCreate;
035 import org.jboss.seam.annotations.Install;
036 import org.jboss.seam.annotations.Logger;
037 import org.jboss.seam.annotations.Name;
038 import org.jboss.seam.annotations.Scope;
039 import org.jboss.seam.annotations.intercept.BypassInterceptors;
040 import org.jboss.seam.async.AbstractDispatcher;
041 import org.jboss.seam.async.Dispatcher;
042 import org.jboss.seam.async.Schedule;
043 import org.jboss.seam.core.Events;
044 import 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
057 public 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 }