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 */
017package org.apache.activemq.web.filter;
018
019import java.io.IOException;
020import java.util.AbstractMap;
021import java.util.Collections;
022import java.util.Map;
023import java.util.Set;
024
025import javax.servlet.Filter;
026import javax.servlet.FilterChain;
027import javax.servlet.FilterConfig;
028import javax.servlet.ServletContext;
029import javax.servlet.ServletException;
030import javax.servlet.ServletRequest;
031import javax.servlet.ServletResponse;
032import javax.servlet.http.HttpServletRequest;
033import javax.servlet.http.HttpServletResponse;
034
035import org.apache.activemq.web.BrokerFacade;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038import org.springframework.web.bind.ServletRequestDataBinder;
039import org.springframework.web.context.WebApplicationContext;
040import org.springframework.web.context.support.WebApplicationContextUtils;
041
042/**
043 * Exposes Spring ApplicationContexts to JSP EL and other view technologies.
044 * Currently a variable is placed in application scope (by default called
045 * 'applicationContext') so that POJOs can be pulled out of Spring in a JSP page
046 * to render things using EL expressions. <br/>
047 * 
048 * e.g. ${applicationContext.cheese} would access the cheese POJO. Or
049 * ${applicationContext.cheese.name} would access the name property of the
050 * cheese POJO. <br/>
051 * 
052 * You can then use JSTL to work with these POJOs such as &lt;c.set var="myfoo"
053 * value="${applicationContext.foo}"/&gt; <br/>
054 * 
055 * In addition to applicationContext a 'requestContext' variable is created
056 * which will automatically bind any request parameters to the POJOs extracted
057 * from the applicationContext - which is ideal for POJOs which implement
058 * queries in view technologies.
059 * 
060 * 
061 */
062public class ApplicationContextFilter implements Filter {
063    private static final transient Logger LOG = LoggerFactory.getLogger(ApplicationContextFilter.class);
064
065    private ServletContext servletContext;
066    private String applicationContextName = "applicationContext";
067    private String requestContextName = "requestContext";
068    private String requestName = "request";
069
070    public void init(FilterConfig config) throws ServletException {
071        this.servletContext = config.getServletContext();
072        this.applicationContextName = getInitParameter(config, "applicationContextName", applicationContextName);
073        this.requestContextName = getInitParameter(config, "requestContextName", requestContextName);
074        this.requestName = getInitParameter(config, "requestName", requestName);
075
076        // register the application context in the applicationScope
077        WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
078        Map wrapper = createApplicationContextWrapper(context);
079        servletContext.setAttribute(applicationContextName, wrapper);
080    }
081
082    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
083        // lets register a requestContext in the requestScope
084        Map requestContextWrapper = createRequestContextWrapper(request);
085        String path = ((HttpServletRequest)request).getRequestURI();
086        // handle slave brokers
087//        try {
088//            if ( !(path.endsWith("css") || path.endsWith("png") || path.endsWith("ico") || path.endsWith(slavePage))
089//                    && ((BrokerFacade)requestContextWrapper.get("brokerQuery")).isSlave()) {
090//                ((HttpServletResponse)response).sendRedirect(slavePage);
091//                return;
092//            }
093//        } catch (Exception e) {
094//            LOG.warn(path + ", failed to access BrokerFacade: reason: " + e.getLocalizedMessage());
095//            if (LOG.isDebugEnabled()) {
096//                LOG.debug(request.toString(), e);
097//            }
098//            throw new IOException(e);
099//        }
100        request.setAttribute(requestContextName, requestContextWrapper);
101        request.setAttribute(requestName, request);
102        chain.doFilter(request, response);
103    }
104
105    public void destroy() {
106    }
107
108    public ServletContext getServletContext() {
109        return servletContext;
110    }
111
112    public String getApplicationContextName() {
113        return applicationContextName;
114    }
115
116    public void setApplicationContextName(String variableName) {
117        this.applicationContextName = variableName;
118    }
119
120    public String getRequestContextName() {
121        return requestContextName;
122    }
123
124    public void setRequestContextName(String requestContextName) {
125        this.requestContextName = requestContextName;
126    }
127
128    protected String getInitParameter(FilterConfig config, String key, String defaultValue) {
129        String parameter = config.getInitParameter(key);
130        return (parameter != null) ? parameter : defaultValue;
131    }
132
133    /**
134     * Creates a wrapper around the web application context so that it can be
135     * accessed easily from inside JSP EL (or other expression languages in
136     * other view technologies).
137     */
138    protected Map createApplicationContextWrapper(final WebApplicationContext context) {
139        Map wrapper = new AbstractMap() {
140
141            public WebApplicationContext getContext() {
142                return context;
143            }
144
145            public Object get(Object key) {
146                if (key == null) {
147                    return null;
148                }
149                return context.getBean(key.toString());
150            }
151
152            public Set entrySet() {
153                return Collections.EMPTY_SET;
154            }
155
156        };
157        return wrapper;
158    }
159
160    /**
161     * Creates a wrapper around the request context (e.g. to allow POJOs to be
162     * auto-injected from request parameter values etc) so that it can be
163     * accessed easily from inside JSP EL (or other expression languages in
164     * other view technologies).
165     */
166    protected Map createRequestContextWrapper(final ServletRequest request) {
167        final WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
168        Map wrapper = new AbstractMap() {
169
170            public WebApplicationContext getContext() {
171                return context;
172            }
173
174            public Object get(Object key) {
175                if (key == null) {
176                    return null;
177                }
178                return bindRequestBean(context.getBean(key.toString()), request);
179            }
180
181            public Set entrySet() {
182                return Collections.EMPTY_SET;
183            }
184
185        };
186        return wrapper;
187
188    }
189
190    /**
191     * Binds properties from the request parameters to the given POJO which is
192     * useful for POJOs which are configurable via request parameters such as
193     * for query/view POJOs
194     */
195    protected Object bindRequestBean(Object bean, ServletRequest request) {
196        ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, null);
197        binder.bind(request);
198        return bean;
199    }
200
201}