View Javadoc

1   /*
2    * $Id: ExtendedValidatorFilter.java 269 2005-08-10 17:49:22Z josem $
3    *
4    * Tarsis
5    * Copyright (C) 2002 Talika Open Source Group
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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      // Constants
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      // Fields
64      /**
65       * History size.
66       */
67      private int historySize = DEFAULT_HISTORY_SIZE;
68  
69      // Methods
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                 // Generic parameter validation
139                 validate(cmd.getParameters(), servletRequest);
140 
141                 // Bussiness parameter validation
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             // HistoricRequest historicRequest = getHistory(
152         }
153         catch (Throwable t) {
154             throw new ServletException(t);
155         }
156 
157         filterChain.doFilter(servletRequest, servletResponse);
158 
159     }
160 
161     // History methods
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         // Save ticket
175         request.setAttribute(Globals.TICKET_ATTR, ticket);
176 
177         // Add request to history
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     // Ticket methods
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 }