1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.talika.tarsis.filters.validator;
24
25 import java.io.IOException;
26 import java.security.MessageDigest;
27 import java.security.NoSuchAlgorithmException;
28
29 import javax.servlet.FilterChain;
30 import javax.servlet.FilterConfig;
31 import javax.servlet.ServletException;
32 import javax.servlet.ServletRequest;
33 import javax.servlet.ServletResponse;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpSession;
36
37 import org.talika.tarsis.Globals;
38 import org.talika.tarsis.command.Command;
39 import org.talika.tarsis.command.RequestImpl;
40 import org.talika.tarsis.command.action.Action;
41
42 /**
43 * Experimental extended validator filter. Work in progress.
44 *
45 * @author Jose M. Palomar
46 * @version $Revision: 269 $
47 * @todo finish extended validator architecture.
48 */
49
50 public class ExtendedValidatorFilter extends ValidatorFilter {
51
52
53 /**
54 * History size parameter name.
55 */
56 private static final String HISTORY_SIZE_PARAM = "history";
57
58 /**
59 * Default history size parameter value.
60 */
61 private static final int DEFAULT_HISTORY_SIZE = 3;
62
63
64 /**
65 * History size.
66 */
67 private int historySize = DEFAULT_HISTORY_SIZE;
68
69
70 /**
71 * Called by the web container to indicate to a filter that it is being placed
72 * into service.<br>
73 * <br>
74 * Initialization consits in calling super <code>init</code> method and storing
75 * in a local variable history size parameter for further use.
76 *
77 * @param filterConfig FilterConfig filter configutarion.
78 * @throws ServletException if an exception has occurred that interferes with the
79 * filter's normal operation
80 * @see javax.servlet.Filter#init(FilterConfig)
81 */
82 public void init(FilterConfig filterConfig) throws ServletException {
83 super.init(filterConfig);
84
85 String historySizeStr = filterConfig.getInitParameter(HISTORY_SIZE_PARAM);
86 if (historySizeStr != null) {
87
88 try {
89 this.historySize = Integer.parseInt(historySizeStr);
90 }
91 catch (NumberFormatException nfe) {
92 this.historySize = DEFAULT_HISTORY_SIZE;
93 }
94
95 }
96 else {
97 this.historySize = DEFAULT_HISTORY_SIZE;
98 }
99
100 }
101
102 /**
103 * Called by the web container to indicate to a filter that it is being taken out
104 * of service.
105 *
106 * @see javax.servlet.Filter#destroy()
107 */
108 public void destroy() {
109 super.destroy();
110 }
111
112 /**
113 * Validates command parameters sent in client's request.
114 *
115 * @param servletRequest ServletRequest the <code>ServletRequest</code> object
116 * that contains the client's request.
117 * @param servletResponse ServletResponse the <code>ServletResponse</code> object
118 * that contains the servlet's response.
119 * @param filterChain FilterChain invocation chain of filtered request.
120 * @throws IOException if an input or output exception occurs
121 * @throws ServletException if an exception has occurred that interferes with the
122 * filter's normal operation
123 * @see javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
124 */
125 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
126 FilterChain filterChain)
127 throws IOException, ServletException {
128
129 if (getLogger().isDebugEnabled()) {
130 getLogger().logDebug(getFilterConfig().getFilterName() + ": invoked");
131 }
132
133 try {
134
135 Command cmd = findCommand(servletRequest);
136 if (cmd != null && cmd.isValidable()) {
137
138
139 validate(cmd.getParameters(), servletRequest);
140
141
142 Action action = cmd.getAction();
143 action.validate(new RequestImpl((HttpServletRequest) servletRequest));
144
145 }
146
147 putHistory(servletRequest);
148
149 }
150 catch (InvalidParametersException ipe) {
151
152 }
153 catch (Throwable t) {
154 throw new ServletException(t);
155 }
156
157 filterChain.doFilter(servletRequest, servletResponse);
158
159 }
160
161
162 /**
163 * Stores client's request in request history.
164 *
165 * @param request ServletRequest client's request.
166 */
167 protected void putHistory(ServletRequest request) {
168
169 HistorySession history = getHistorySession((HttpServletRequest) request);
170 String ticket = generateTicket((HttpServletRequest) request);
171 HistoricRequest historicRequest =
172 new HistoricRequest(ticket, (HttpServletRequest) request);
173
174
175 request.setAttribute(Globals.TICKET_ATTR, ticket);
176
177
178 history.add(historicRequest);
179
180 }
181
182 /**
183 * Retrieves client's request from request history.
184 *
185 * @param request ServletRequest client'r request.
186 * @return HistoricRequest hitoric client's request.
187 */
188 protected HistoricRequest getHistory(ServletRequest request) {
189
190 HistorySession history = getHistorySession((HttpServletRequest) request);
191 String ticket = request.getParameter(Globals.TICKET_PARAMETER);
192 return history.find(ticket);
193
194 }
195
196 /**
197 * Obtains history session from client's request. If there is no history session
198 * creates a new one.
199 *
200 * @param request HttpServletRequest client's request.
201 * @return HistorySession history session.
202 */
203 private HistorySession getHistorySession(HttpServletRequest request) {
204 HistorySession historySession = (HistorySession) request.getSession().getAttribute(Globals.HISTORY_SESSION_ATTR);
205 if (historySession == null) {
206 historySession = new HistorySession(historySize);
207 request.getSession().setAttribute(Globals.HISTORY_SESSION_ATTR, historySession);
208 }
209 return historySession;
210 }
211
212
213 /**
214 * Generates a ticket code for client's request.
215 *
216 * @param request HttpServletRequest client's request.
217 * @return String ticket.
218 */
219 private String generateTicket(HttpServletRequest request) {
220
221 HttpSession session = request.getSession();
222 try {
223 byte[] id = session.getId().getBytes();
224 byte[] now =
225 new Long(System.currentTimeMillis()).toString().getBytes();
226 MessageDigest md = MessageDigest.getInstance("MD5");
227 md.update(id);
228 md.update(now);
229 return (toHex(md.digest()));
230 }
231 catch (IllegalStateException e) {
232 return (null);
233 }
234 catch (NoSuchAlgorithmException e) {
235 return (null);
236 }
237
238 }
239
240 /**
241 * Converts an array of bytes in an hexadecimal <code>String</code>.
242 *
243 * @param buffer byte[] array to convert.
244 * @return String a <code>String</code> resulting from converting array of bytes.
245 */
246 private String toHex(byte[] buffer) {
247
248 StringBuffer sb = new StringBuffer();
249 for (int i = 0; i < buffer.length; i++) {
250 sb.append(Integer.toHexString((int) buffer[i] & 0xff));
251 }
252 return (sb.toString());
253
254 }
255
256 }