001 package com.mockrunner.mock.web;
002
003 import java.io.IOException;
004 import java.util.ArrayList;
005 import java.util.Collections;
006 import java.util.Iterator;
007 import java.util.List;
008
009 import javax.servlet.Filter;
010 import javax.servlet.FilterChain;
011 import javax.servlet.Servlet;
012 import javax.servlet.ServletException;
013 import javax.servlet.ServletRequest;
014 import javax.servlet.ServletResponse;
015
016 import org.apache.commons.logging.Log;
017 import org.apache.commons.logging.LogFactory;
018
019 import com.mockrunner.base.NestedApplicationException;
020
021 /**
022 * Mock implementation of <code>FilterChain</code>.
023 */
024 public class MockFilterChain implements FilterChain
025 {
026 private final static Log log = LogFactory.getLog(MockFilterChain.class);
027 private List filters = new ArrayList();
028 private Servlet servlet;
029 private Iterator iterator;
030 private List requestList = new ArrayList();
031 private List responseList = new ArrayList();
032
033 public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException
034 {
035 requestList.add(request);
036 responseList.add(response);
037 if(null == iterator)
038 {
039 iterator = filters.iterator();
040 }
041 if(iterator.hasNext())
042 {
043 Filter nextFilter = (Filter)iterator.next();
044 nextFilter.doFilter(request, response, this);
045 }
046 else
047 {
048 reset();
049 if(null == servlet) return;
050 servlet.service(request, response);
051 }
052 }
053
054 /**
055 * Resets the internal iterator of this chain.
056 */
057 public void reset()
058 {
059 iterator = null;
060 }
061
062 /**
063 * Adds a filter to the chain.
064 * @param filter the filter
065 */
066 public void addFilter(Filter filter)
067 {
068 filters.add(filter);
069 }
070
071 /**
072 * Adds a filter to the chain. The filter must implement
073 * <code>javax.servlet.Filter</code>.
074 * @param filterClass the filter class
075 * @throws IllegalArgumentException if the specified class does not implement
076 * <code>javax.servlet.Filter</code>
077 */
078 public void addFilter(Class filterClass)
079 {
080 if(!Filter.class.isAssignableFrom(filterClass))
081 {
082 throw new IllegalArgumentException("filterClass must be an instance of javax.servlet.Filter");
083 }
084 try
085 {
086 filters.add(filterClass.newInstance());
087 }
088 catch(Exception exc)
089 {
090 log.error(exc.getMessage(), exc);
091 throw new NestedApplicationException(exc);
092 }
093 }
094
095 /**
096 * Sets the servlet that is called at the end of the chain.
097 * @param servlet the servlet
098 */
099 public void setServlet(Servlet servlet)
100 {
101 this.servlet = servlet;
102 }
103
104 /**
105 * Clears all filters and sets the current servlet to <code>null</code>.
106 */
107 public void release()
108 {
109 filters.clear();
110 setServlet(null);
111 reset();
112 }
113
114 /**
115 * Returns the list of all request objects used to call
116 * {@link #doFilter} when iterating through the chain.
117 * @return the request list
118 */
119 public List getRequestList()
120 {
121 return Collections.unmodifiableList(requestList);
122 }
123
124 /**
125 * Returns the list of all response objects used to call
126 * {@link #doFilter} when iterating through the chain.
127 * @return the response list
128 */
129 public List getResponseList()
130 {
131 return Collections.unmodifiableList(responseList);
132 }
133
134 /**
135 * Returns the last request, usually the request that was
136 * used to call the final servlet. Returns <code>null</code>
137 * if no request is specified, e.g. if the chain wasn't called.
138 * Otherwise returns the last entry of the list returned by
139 * {@link #getRequestList}.
140 * @return the last request
141 */
142 public ServletRequest getLastRequest()
143 {
144 if(requestList.isEmpty()) return null;
145 return (ServletRequest)requestList.get(requestList.size() - 1);
146 }
147
148 /**
149 * Returns the last response, usually the response that was
150 * used to call the final servlet. Returns <code>null</code>
151 * if no response is specified, e.g. if the chain wasn't called.
152 * Otherwise returns the last entry of the list returned by
153 * {@link #getResponseList}.
154 * @return the last response
155 */
156 public ServletResponse getLastResponse()
157 {
158 if(responseList.isEmpty()) return null;
159 return (ServletResponse)responseList.get(responseList.size() - 1);
160 }
161 }