001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.seam21;
022
023 import java.io.IOException;
024 import java.util.ArrayList;
025 import java.util.HashMap;
026 import java.util.List;
027
028 import javax.servlet.FilterChain;
029 import javax.servlet.FilterConfig;
030 import javax.servlet.ServletException;
031 import javax.servlet.ServletRequest;
032 import javax.servlet.ServletResponse;
033 import javax.servlet.http.HttpServletRequest;
034 import javax.servlet.http.HttpServletResponse;
035
036 import org.granite.config.GraniteConfig;
037 import org.granite.config.flex.Channel;
038 import org.granite.config.flex.Destination;
039 import org.granite.config.flex.EndPoint;
040 import org.granite.config.flex.Factory;
041 import org.granite.config.flex.Service;
042 import org.granite.config.flex.ServicesConfig;
043 import org.granite.logging.Logger;
044 import org.granite.messaging.amf.process.AMF3MessageInterceptor;
045 import org.granite.messaging.service.ExceptionConverter;
046 import org.granite.messaging.service.tide.TideComponentAnnotatedWithMatcher;
047 import org.granite.messaging.service.tide.TideComponentInstanceOfMatcher;
048 import org.granite.messaging.service.tide.TideComponentNameMatcher;
049 import org.granite.messaging.service.tide.TideComponentTypeMatcher;
050 import org.granite.messaging.webapp.AMFEndpoint;
051 import org.granite.util.XMap;
052 import org.jboss.seam.Component;
053 import org.jboss.seam.ScopeType;
054 import org.jboss.seam.annotations.Create;
055 import org.jboss.seam.annotations.Install;
056 import org.jboss.seam.annotations.Name;
057 import org.jboss.seam.annotations.Scope;
058 import org.jboss.seam.annotations.Startup;
059 import org.jboss.seam.annotations.intercept.BypassInterceptors;
060 import org.jboss.seam.web.AbstractFilter;
061
062
063 @Scope(ScopeType.APPLICATION)
064 @Name("org.granite.seam.serverFilter")
065 @Startup
066 @Install(precedence=Install.BUILT_IN, value=false, classDependencies={"org.granite.seam21.Seam21GraniteConfig"})
067 @BypassInterceptors
068 @org.jboss.seam.annotations.web.Filter
069 public class ServerFilter extends AbstractFilter {
070
071 private static final Logger log = Logger.getLogger(ServerFilter.class);
072
073 private FilterConfig config = null;
074 private GraniteConfig graniteConfig = null;
075 private ServicesConfig servicesConfig = null;
076
077 private List<String> tideRoles = null;
078 private List<String> tideAnnotations = null;
079 private List<String> tideInterfaces = null;
080 private List<String> tideNames = null;
081 private List<String> tideTypes = null;
082 private List<Class<? extends ExceptionConverter>> exceptionConverters = null;
083 private AMF3MessageInterceptor amf3MessageInterceptor = null;
084 private boolean tide = false;
085 private String type = "server";
086
087 private AMFEndpoint amfEndpoint = null;
088
089
090 public ServerFilter() {
091 super();
092 setUrlPattern("/graniteamf/*");
093 }
094
095
096 @Override
097 public void init(FilterConfig config) throws ServletException {
098 super.init(config);
099
100 this.config = config;
101
102 this.amfEndpoint = new AMFEndpoint();
103 this.amfEndpoint.init(config.getServletContext());
104 }
105
106
107 @Override
108 public void destroy() {
109 super.destroy();
110
111 this.config = null;
112
113 this.amfEndpoint.destroy();
114 this.amfEndpoint = null;
115 }
116
117
118 @Create
119 public void seamInit() {
120 Seam21GraniteConfig seam21GraniteConfig = (Seam21GraniteConfig)Component.getInstance(Seam21GraniteConfig.class, true);
121
122 this.graniteConfig = seam21GraniteConfig.getGraniteConfig();
123 if (tideAnnotations != null) {
124 for (String ta : tideAnnotations) {
125 try {
126 this.graniteConfig.getTideComponentMatchers().add(new TideComponentAnnotatedWithMatcher(ta, false));
127 log.debug("Enabled components annotated with %s for Tide remoting", ta);
128 }
129 catch (Exception e) {
130 log.error(e, "Could not add tide-component annotation %s", ta);
131 }
132 }
133 }
134 if (tideInterfaces != null) {
135 for (String ti : tideInterfaces) {
136 try {
137 this.graniteConfig.getTideComponentMatchers().add(new TideComponentInstanceOfMatcher(ti, false));
138 log.debug("Enabled components extending %s for Tide remoting", ti);
139 }
140 catch (Exception e) {
141 log.error(e, "Could not add tide-component interface %s", ti);
142 }
143 }
144 }
145 if (tideNames != null) {
146 for (String tn : tideNames) {
147 try {
148 this.graniteConfig.getTideComponentMatchers().add(new TideComponentNameMatcher(tn, false));
149 log.debug("Enabled components named like %s for Tide remoting", tn);
150 }
151 catch (Exception e) {
152 log.error(e, "Could not add tide-component name %s", tn);
153 }
154 }
155 }
156 if (tideTypes != null) {
157 for (String tt : tideTypes) {
158 try {
159 this.graniteConfig.getTideComponentMatchers().add(new TideComponentTypeMatcher(tt, false));
160 log.debug("Enabled components with type %s for Tide remoting", tt);
161 }
162 catch (Exception e) {
163 log.error(e, "Could not add tide-component type %s", tt);
164 }
165 }
166 }
167 if (exceptionConverters != null) {
168 for (Class<? extends ExceptionConverter> ec : exceptionConverters) {
169 this.graniteConfig.registerExceptionConverter(ec);
170 log.debug("Registered exception converter %s", ec);
171 }
172 }
173 if (amf3MessageInterceptor != null)
174 this.graniteConfig.setAmf3MessageInterceptor(amf3MessageInterceptor);
175
176 servicesConfig = seam21GraniteConfig.getServicesConfig();
177
178 Channel channel = servicesConfig.findChannelById("graniteamf");
179 if (channel == null) {
180 channel = new Channel("graniteamf", "mx.messaging.channels.AMFChannel",
181 new EndPoint("http://{server.name}:{server.port}/{context.root}/graniteamf/amf", "flex.messaging.endpoints.AMFEndpoint"),
182 new XMap());
183 servicesConfig.addChannel(channel);
184 }
185
186 if (tide) {
187 Factory factory = servicesConfig.findFactoryById("tide-seam-factory");
188 if (factory == null) {
189 factory = new Factory("tide-seam-factory", "org.granite.tide.seam.SeamServiceFactory", new XMap());
190 servicesConfig.addFactory(factory);
191 }
192
193 Service service = servicesConfig.findServiceById("granite-service");
194 if (service == null) {
195 service = new Service("granite-service", "flex.messaging.services.RemotingService",
196 "flex.messaging.messages.RemotingMessage", null, null, new HashMap<String, Destination>());
197 }
198 Destination destination = servicesConfig.findDestinationById("flex.messaging.messages.RemotingMessage", type);
199 if (destination == null) {
200 List<String> channelIds = new ArrayList<String>();
201 channelIds.add("graniteamf");
202 destination = new Destination(type, channelIds, new XMap(), tideRoles, null, null);
203 destination.getProperties().put("factory", factory.getId());
204 destination.getProperties().put("validator-name", "tideValidator");
205 service.getDestinations().put(destination.getId(), destination);
206 servicesConfig.addService(service);
207 }
208
209 log.info("Registered Tide/Seam service factory and destination");
210 }
211 else {
212 Factory factory = new Factory("seam-factory", "org.granite.seam.SeamServiceFactory", new XMap());
213 servicesConfig.addFactory(factory);
214
215 Service service = new Service("granite-service", "flex.messaging.services.RemotingService",
216 "flex.messaging.messages.RemotingMessage", null, null, new HashMap<String, Destination>());
217 servicesConfig.addService(service);
218
219 servicesConfig.scan(null);
220
221 log.info("Registered Seam service factory");
222 }
223 }
224
225 public void setTideRoles(List<String> tideRoles) {
226 this.tideRoles = tideRoles;
227 }
228
229 public void setTideAnnotations(List<String> tideAnnotations) {
230 this.tideAnnotations = tideAnnotations;
231 }
232
233 public void setTideInterfaces(List<String> tideInterfaces) {
234 this.tideInterfaces = tideInterfaces;
235 }
236
237 public void setTideNames(List<String> tideNames) {
238 this.tideNames = tideNames;
239 }
240
241 public void setTideTypes(List<String> tideTypes) {
242 this.tideTypes = tideTypes;
243 }
244
245 public void setExceptionConverters(List<Class<? extends ExceptionConverter>> exceptionConverters) {
246 this.exceptionConverters = exceptionConverters;
247 }
248
249 public void setAmf3MessageInterceptor(AMF3MessageInterceptor amf3MessageInterceptor) {
250 this.amf3MessageInterceptor = amf3MessageInterceptor;
251 }
252
253 public void setTide(boolean tide) {
254 this.tide = tide;
255 }
256
257 public void setType(String type) {
258 this.type = type;
259 }
260
261
262 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
263 throws IOException, ServletException {
264 if (isMappedToCurrentRequestPath(request)) {
265 amfEndpoint.service(
266 graniteConfig, servicesConfig, config.getServletContext(),
267 (HttpServletRequest)request, (HttpServletResponse)response
268 );
269 }
270 else {
271 chain.doFilter(request, response);
272 }
273 }
274 }