001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2014 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 */ 022package org.granite.seam21; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028 029import javax.servlet.FilterChain; 030import javax.servlet.FilterConfig; 031import javax.servlet.ServletException; 032import javax.servlet.ServletRequest; 033import javax.servlet.ServletResponse; 034import javax.servlet.http.HttpServletRequest; 035import javax.servlet.http.HttpServletResponse; 036 037import org.granite.config.GraniteConfig; 038import org.granite.config.flex.Channel; 039import org.granite.config.flex.Destination; 040import org.granite.config.flex.EndPoint; 041import org.granite.config.flex.Factory; 042import org.granite.config.flex.Service; 043import org.granite.config.flex.ServicesConfig; 044import org.granite.logging.Logger; 045import org.granite.messaging.amf.process.AMF3MessageInterceptor; 046import org.granite.messaging.service.ExceptionConverter; 047import org.granite.messaging.service.tide.TideComponentAnnotatedWithMatcher; 048import org.granite.messaging.service.tide.TideComponentInstanceOfMatcher; 049import org.granite.messaging.service.tide.TideComponentNameMatcher; 050import org.granite.messaging.service.tide.TideComponentTypeMatcher; 051import org.granite.messaging.webapp.AMFEndpoint; 052import org.granite.util.XMap; 053import org.jboss.seam.Component; 054import org.jboss.seam.ScopeType; 055import org.jboss.seam.annotations.Create; 056import org.jboss.seam.annotations.Install; 057import org.jboss.seam.annotations.Name; 058import org.jboss.seam.annotations.Scope; 059import org.jboss.seam.annotations.Startup; 060import org.jboss.seam.annotations.intercept.BypassInterceptors; 061import 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 070public 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}