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.flexFilter")
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 FlexFilter extends AbstractFilter {
070
071 private static final Logger log = Logger.getLogger(FlexFilter.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
086
087 public FlexFilter() {
088 super();
089 setUrlPattern("/graniteamf/*");
090 }
091
092
093 @Override
094 public void init(FilterConfig config) {
095 this.config = config;
096 }
097
098
099 @Create
100 public void seamInit() {
101 Seam21GraniteConfig seam21GraniteConfig = (Seam21GraniteConfig)Component.getInstance(Seam21GraniteConfig.class, true);
102
103 this.graniteConfig = seam21GraniteConfig.getGraniteConfig();
104 if (tideAnnotations != null) {
105 for (String ta : tideAnnotations) {
106 try {
107 this.graniteConfig.getTideComponentMatchers().add(new TideComponentAnnotatedWithMatcher(ta, false));
108 log.debug("Enabled components annotated with %s for Tide remoting", ta);
109 }
110 catch (Exception e) {
111 log.error(e, "Could not add tide-component annotation %s", ta);
112 }
113 }
114 }
115 if (tideInterfaces != null) {
116 for (String ti : tideInterfaces) {
117 try {
118 this.graniteConfig.getTideComponentMatchers().add(new TideComponentInstanceOfMatcher(ti, false));
119 log.debug("Enabled components extending %s for Tide remoting", ti);
120 }
121 catch (Exception e) {
122 log.error(e, "Could not add tide-component interface %s", ti);
123 }
124 }
125 }
126 if (tideNames != null) {
127 for (String tn : tideNames) {
128 try {
129 this.graniteConfig.getTideComponentMatchers().add(new TideComponentNameMatcher(tn, false));
130 log.debug("Enabled components named like %s for Tide remoting", tn);
131 }
132 catch (Exception e) {
133 log.error(e, "Could not add tide-component name %s", tn);
134 }
135 }
136 }
137 if (tideTypes != null) {
138 for (String tt : tideTypes) {
139 try {
140 this.graniteConfig.getTideComponentMatchers().add(new TideComponentTypeMatcher(tt, false));
141 log.debug("Enabled components with type %s for Tide remoting", tt);
142 }
143 catch (Exception e) {
144 log.error(e, "Could not add tide-component type %s", tt);
145 }
146 }
147 }
148 if (exceptionConverters != null) {
149 for (Class<? extends ExceptionConverter> ec : exceptionConverters) {
150 this.graniteConfig.registerExceptionConverter(ec);
151 log.debug("Registered exception converter %s", ec);
152 }
153 }
154 if (amf3MessageInterceptor != null)
155 this.graniteConfig.setAmf3MessageInterceptor(amf3MessageInterceptor);
156
157 servicesConfig = seam21GraniteConfig.getServicesConfig();
158
159 Channel channel = servicesConfig.findChannelById("graniteamf");
160 if (channel == null) {
161 channel = new Channel("graniteamf", "mx.messaging.channels.AMFChannel",
162 new EndPoint("http://{server.name}:{server.port}/{context.root}/graniteamf/amf", "flex.messaging.endpoints.AMFEndpoint"),
163 new XMap());
164 servicesConfig.addChannel(channel);
165 }
166
167 if (tide) {
168 Factory factory = servicesConfig.findFactoryById("tide-seam-factory");
169 if (factory == null) {
170 factory = new Factory("tide-seam-factory", "org.granite.tide.seam.SeamServiceFactory", new XMap());
171 servicesConfig.addFactory(factory);
172 }
173
174 Service service = servicesConfig.findServiceById("granite-service");
175 if (service == null) {
176 service = new Service("granite-service", "flex.messaging.services.RemotingService",
177 "flex.messaging.messages.RemotingMessage", null, null, new HashMap<String, Destination>());
178 }
179 Destination destination = servicesConfig.findDestinationById("flex.messaging.messages.RemotingMessage", "seam");
180 if (destination == null) {
181 List<String> channelIds = new ArrayList<String>();
182 channelIds.add("graniteamf");
183 destination = new Destination("seam", channelIds, new XMap(), tideRoles, null, null);
184 destination.getProperties().put("factory", factory.getId());
185 destination.getProperties().put("validator-name", "tideValidator");
186 service.getDestinations().put(destination.getId(), destination);
187 servicesConfig.addService(service);
188 }
189
190 log.info("Registered Tide/Seam service factory and destination");
191 }
192 else {
193 Factory factory = new Factory("seam-factory", "org.granite.seam.SeamServiceFactory", new XMap());
194 servicesConfig.addFactory(factory);
195
196 Service service = new Service("granite-service", "flex.messaging.services.RemotingService",
197 "flex.messaging.messages.RemotingMessage", null, null, new HashMap<String, Destination>());
198 servicesConfig.addService(service);
199
200 servicesConfig.scan(null);
201
202 log.info("Registered Seam service factory");
203 }
204 }
205
206 public void setTideRoles(List<String> tideRoles) {
207 this.tideRoles = tideRoles;
208 }
209
210 public void setTideAnnotations(List<String> tideAnnotations) {
211 this.tideAnnotations = tideAnnotations;
212 }
213
214 public void setTideInterfaces(List<String> tideInterfaces) {
215 this.tideInterfaces = tideInterfaces;
216 }
217
218 public void setTideNames(List<String> tideNames) {
219 this.tideNames = tideNames;
220 }
221
222 public void setTideTypes(List<String> tideTypes) {
223 this.tideTypes = tideTypes;
224 }
225
226 public void setExceptionConverters(List<Class<? extends ExceptionConverter>> exceptionConverters) {
227 this.exceptionConverters = exceptionConverters;
228 }
229
230 public void setAmf3MessageInterceptor(AMF3MessageInterceptor amf3MessageInterceptor) {
231 this.amf3MessageInterceptor = amf3MessageInterceptor;
232 }
233
234 public void setTide(boolean tide) {
235 this.tide = tide;
236 }
237
238
239 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
240 throws IOException, ServletException {
241 if (isMappedToCurrentRequestPath(request)) {
242 AMFEndpoint.service(graniteConfig, servicesConfig, config.getServletContext(),
243 (HttpServletRequest)request, (HttpServletResponse)response);
244 }
245 else {
246 chain.doFilter(request, response);
247 }
248 }
249 }