001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.jetty6;
018    
019    import java.util.Collection;
020    import java.util.Arrays;
021    
022    import org.apache.geronimo.gbean.GBeanInfo;
023    import org.apache.geronimo.gbean.GBeanInfoBuilder;
024    import org.apache.geronimo.gbean.ReferenceCollection;
025    import org.apache.geronimo.gbean.ReferenceCollectionEvent;
026    import org.apache.geronimo.gbean.ReferenceCollectionListener;
027    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
028    import org.mortbay.jetty.Handler;
029    import org.mortbay.jetty.servlet.FilterMapping;
030    import org.mortbay.jetty.servlet.ServletHandler;
031    
032    /**
033     * @version $Rev: 550559 $ $Date: 2007-06-25 13:33:39 -0400 (Mon, 25 Jun 2007) $
034     */
035    public class JettyFilterMapping extends FilterMapping {
036    
037        private final String[] urlPatterns;
038        private final boolean requestDispatch;
039        private final boolean forwardDispatch;
040        private final boolean includeDispatch;
041        private final boolean errorDispatch;
042        private final JettyFilterHolder jettyFilterHolder;
043        private final Collection<JettyServletHolder> jettyServletHolders;
044        private final JettyFilterMapping previous;
045        private final JettyServletRegistration jettyServletRegistration;
046    
047        //todo use an interface for endpoints.
048        public JettyFilterMapping() {
049            this.urlPatterns = null;
050            this.requestDispatch = false;
051            this.forwardDispatch = false;
052            this.includeDispatch = false;
053            this.errorDispatch = false;
054            this.jettyFilterHolder = null;
055            this.jettyServletHolders = null;
056            this.previous = null;
057            this.jettyServletRegistration = null;
058        }
059    
060        public JettyFilterMapping(String[] urlPatterns,
061                boolean requestDispatch,
062                boolean forwardDispatch,
063                boolean includeDispatch,
064                boolean errorDispatch,
065                JettyFilterHolder jettyFilterHolder,
066                Collection<JettyServletHolder> jettyServletHolders,
067                JettyFilterMapping previous,
068                JettyServletRegistration jettyServletRegistration) {
069            this.urlPatterns = urlPatterns;
070            this.requestDispatch = requestDispatch;
071            this.forwardDispatch = forwardDispatch;
072            this.includeDispatch = includeDispatch;
073            this.errorDispatch = errorDispatch;
074            this.jettyFilterHolder = jettyFilterHolder;
075            this.jettyServletHolders = jettyServletHolders;
076            this.previous = previous;
077            this.jettyServletRegistration = jettyServletRegistration;
078    
079            if (jettyServletRegistration != null) {
080                assert jettyServletHolders != null ^ urlPatterns != null;
081    
082                String filterName = jettyFilterHolder.getFilterName();
083                int dispatches = 0;
084                if (requestDispatch) {
085                    dispatches |= Handler.REQUEST;
086                }
087                if (forwardDispatch) {
088                    dispatches |= Handler.FORWARD;
089                }
090                if (includeDispatch) {
091                    dispatches |= Handler.INCLUDE;
092                }
093                if (errorDispatch) {
094                    dispatches |= Handler.ERROR;
095                }
096    
097    
098                setFilterName(filterName);
099                setDispatches(dispatches);
100                setPathSpecs(urlPatterns);
101                if (jettyServletHolders != null) {
102                    resetServlets();
103                    if (jettyServletHolders instanceof ReferenceCollection) {
104                        ((ReferenceCollection) jettyServletHolders).addReferenceCollectionListener(new ReferenceCollectionListener() {
105    
106                            public void memberAdded(ReferenceCollectionEvent event) {
107                                resetServlets();
108                                resetJettyFilterMappings();
109                            }
110    
111                            public void memberRemoved(ReferenceCollectionEvent event) {
112                                resetServlets();
113                                resetJettyFilterMappings();
114                            }
115                        });
116                    }
117                }
118    
119                jettyServletRegistration.getServletHandler().addFilterMapping(this);
120            }
121        }
122    
123        private void resetJettyFilterMappings() {
124            //This causes jetty to recompute the filter to servlet mappings based on the
125            //current servlet names in the filter mappings.  Pretty inefficient.
126            ServletHandler servletHandler = jettyServletRegistration.getServletHandler();
127            FilterMapping[] filterMappings = servletHandler.getFilterMappings();
128            FilterMapping[] copy = filterMappings.clone();
129            servletHandler.setFilterMappings(copy);
130        }
131    
132        private void resetServlets() {
133            String[] servletNames = new String[jettyServletHolders.size()];
134            int i = 0;
135            for (JettyServletHolder jettyServletHolder : jettyServletHolders) {
136                servletNames[i++] = jettyServletHolder.getServletName();
137            }
138            setServletNames(servletNames);
139        }
140    
141        public String[] getUrlPatterns() {
142            return urlPatterns;
143        }
144    
145        public boolean isRequestDispatch() {
146            return requestDispatch;
147        }
148    
149        public boolean isForwardDispatch() {
150            return forwardDispatch;
151        }
152    
153        public boolean isIncludeDispatch() {
154            return includeDispatch;
155        }
156    
157        public boolean isErrorDispatch() {
158            return errorDispatch;
159        }
160    
161        public JettyFilterHolder getFilter() {
162            return jettyFilterHolder;
163        }
164    
165        public Collection<JettyServletHolder> getServlets() {
166            return jettyServletHolders;
167        }
168    
169        public JettyFilterMapping getPrevious() {
170            return previous;
171        }
172    
173        public JettyServletRegistration getJettyServletRegistration() {
174            return jettyServletRegistration;
175        }
176    
177        public static final GBeanInfo GBEAN_INFO;
178    
179        static {
180            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyFilterMapping.class, NameFactory.URL_WEB_FILTER_MAPPING);
181            infoBuilder.addAttribute("urlPatterns", String[].class, true);
182            infoBuilder.addAttribute("requestDispatch", boolean.class, true);
183            infoBuilder.addAttribute("forwardDispatch", boolean.class, true);
184            infoBuilder.addAttribute("includeDispatch", boolean.class, true);
185            infoBuilder.addAttribute("errorDispatch", boolean.class, true);
186    
187            infoBuilder.addReference("Filter", JettyFilterHolder.class, NameFactory.WEB_FILTER);
188            infoBuilder.addReference("Servlets", JettyServletHolder.class, NameFactory.SERVLET);
189            infoBuilder.addReference("Previous", JettyFilterMapping.class, NameFactory.URL_WEB_FILTER_MAPPING);
190            infoBuilder.addReference("JettyServletRegistration", JettyServletRegistration.class, NameFactory.WEB_MODULE);
191    
192            infoBuilder.setConstructor(new String[]{"urlPatterns",
193                    "requestDispatch",
194                    "forwardDispatch",
195                    "includeDispatch",
196                    "errorDispatch",
197                    "Filter",
198                    "Servlets",
199                    "Previous",
200                    "JettyServletRegistration"});
201    
202            GBEAN_INFO = infoBuilder.getBeanInfo();
203        }
204    
205        public static GBeanInfo getGBeanInfo() {
206            return GBEAN_INFO;
207        }
208    }