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