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    }