View Javadoc

1   /*
2    * Copyright 2002-2004 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  package net.sf.fridaymvc;
18  
19  import java.io.File;
20  import java.security.AccessControlException;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.servlet.ServletContext;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import net.sf.fridaymvc.actions.Action;
33  import net.sf.fridaymvc.managers.view.ActionViewManager;
34  import net.sf.fridaymvc.managers.view.LayoutViewManager;
35  import net.sf.fridaymvc.managers.view.LinkViewManager;
36  import net.sf.fridaymvc.metadata.commons.AccessLoggedAttribute;
37  import net.sf.fridaymvc.metadata.commons.AccessPermissionAttribute;
38  import net.sf.fridaymvc.metadata.commons.AccessRoleAttribute;
39  import net.sf.fridaymvc.metadata.commons.ActionAttribute;
40  import net.sf.fridaymvc.metadata.commons.ModelAttribute;
41  import net.sf.fridaymvc.metadata.commons.RegExpValidatorAttribute;
42  import net.sf.fridaymvc.models.Model;
43  import net.sf.fridaymvc.security.accesscontroller.AccessController;
44  import net.sf.fridaymvc.security.accesscontroller.User;
45  
46  import org.apache.commons.attributes.Attributes;
47  import org.springframework.beans.BeansException;
48  import org.springframework.context.ApplicationContext;
49  import org.springframework.context.ApplicationContextAware;
50  import org.springframework.web.context.WebApplicationContext;
51  import org.springframework.web.servlet.ViewResolver;
52  
53  /***
54   * @author <a href="mailto:arto.pastinen@ofw.fi">Arto Pastinen</a>
55   * @version $Id: RunData.java,v 1.2 2004/11/23 20:35:56 artsi Exp $
56   */
57  public class RunData implements ApplicationContextAware {
58      public static final String ACTION_VALIDATE_FAILED_FIELDS = "ACTION_VALIDATE_FAILED_FIELDS";
59      
60      protected final ThreadLocal httpServletRequest = new ThreadLocal();
61      protected final ThreadLocal httpServletResponse = new ThreadLocal();
62      
63      protected final ThreadLocal currentViewName = new ThreadLocal();
64      protected final ThreadLocal currentViewUid = new ThreadLocal();
65      
66      protected WebApplicationContext webApplicationContext;
67      
68      protected LayoutViewManager layoutViewManager;
69      protected LinkViewManager linkViewManager;
70      protected ActionViewManager actionViewManager;
71      
72      protected Map preViewMappings; 
73      protected ViewResolver viewResolver;
74          
75      protected Parameters parameters;    
76      protected Map viewMapping;
77      
78      protected AccessController accessController;
79      
80      private static RunData instance;
81      
82      public RunData() {        
83          RunData.instance = this;
84      }
85      
86      private static boolean initialized = false;
87      
88      private void initialize() throws Exception {
89          ServletContext sc = getWebApplicationContext().getServletContext(); 
90          File f = new File(sc.getRealPath("/WEB-INF/classes"));
91          String rootPath = f.getAbsolutePath();
92          scanDirectories(f, rootPath);
93          initialized = true;
94      }
95      
96      private void scanDirectories(File f, String rootPath ) {
97          if(f.isDirectory()) {
98              File files[] = f.listFiles();
99              for(int i = 0; i < files.length; i++) {
100                 scanDirectories(files[i], rootPath);
101             }
102         }
103         else {
104             String ap = f.getAbsolutePath();
105             String tmp[] = f.getAbsolutePath().substring(rootPath.length()+1, ap.length()).split("//.");            
106             if(tmp.length != 2) return;
107             
108             String finalClassName = tmp[0].replace('/', '.');
109             
110             try {
111                 Class c = Class.forName(finalClassName);
112                 ModelAttribute modelAttribute = (ModelAttribute) Attributes.getAttribute(c, ModelAttribute.class);
113                 if(modelAttribute != null) {                    
114                     modelClasses.put(modelAttribute.getName(), c);
115                     return;
116                 }                
117                 ActionAttribute actionAttribute = (ActionAttribute) Attributes.getAttribute(c, ActionAttribute.class);
118                 if(actionAttribute != null) {
119                     actionClasses.put(actionAttribute.getName(), c); 
120                 }
121             }
122             catch(Throwable t) {
123                 // ignore
124             }
125         }
126     }
127     
128     protected Map actionClasses = new HashMap();
129     protected Map modelClasses = new HashMap();
130     
131     public void handleRequest() throws Exception {
132         if(!initialized) {
133             synchronized(this) {
134                 if(!initialized) initialize();
135             }
136         }
137         try {
138             handleAction();
139         }
140         catch(AccessControlException ace) {
141             ace.printStackTrace();
142             renderView("accessdenied", null);
143             return;
144         }
145         includeRootPage();
146     }
147 
148     /***
149      * 
150      * @throws Exception
151      * 
152      */
153     protected void handleAction() throws Exception {
154         Parameters p = getParameters();
155         String actionName = p.get("action");
156         if(actionName == null) return;
157 
158         Class actionClass = (Class) actionClasses.get(actionName);
159         
160         if(actionClass == null && actionName.equals("setpanel")) actionClass = Class.forName("net.sf.fridaymvc.actions.SetPanel");
161 
162         if(actionClass == null) throw new ClassNotFoundException("Cannot find class for action: " + new String(actionName));
163         
164         AccessRoleAttribute ara = (AccessRoleAttribute) Attributes.getAttribute(actionClass, AccessRoleAttribute.class);
165         if(ara != null && !getAccessController().hasRole(ara.getName())) throw new AccessControlException("User dont have required role");
166         AccessPermissionAttribute apa = (AccessPermissionAttribute) Attributes.getAttribute(actionClass, AccessPermissionAttribute.class);
167         if(apa != null && !getAccessController().hasPermission(apa.getName())) throw new AccessControlException("User dont have required permission");
168                 
169         Action action = (Action) actionClass.newInstance();        
170         setCurrentAction(action);        
171         
172         p.setPrefix("action.");
173         
174         Collection validators = Attributes.getAttributes(actionClass, RegExpValidatorAttribute.class);
175         
176         boolean passValidation = true;
177         
178         if(validators.size() > 0) {            
179             for (Iterator iter = validators.iterator(); iter.hasNext();) {
180                 RegExpValidatorAttribute validator = (RegExpValidatorAttribute) iter.next();                
181                 if(validator.passValidation() == false) passValidation = false;    
182             }
183         }        
184         
185        if(!passValidation) {
186            p.setPrefix(null);
187            return;
188        }
189         
190         try {
191             action.service();
192         }
193         finally {
194             p.setPrefix(null);
195         }        
196     }
197     
198     public void includePanel(String uid, String viewName) throws Exception {
199         Map tmp = getViewMapping();
200         synchronized(tmp) {
201             if(tmp.containsKey(uid)) viewName = (String) tmp.get(uid);
202         }
203         
204         setCurrentViewName(viewName);
205         setCurrentViewUid(uid);
206         try {
207             include(uid, viewName);
208         }
209         catch(Exception e) {
210             e.printStackTrace();
211             setCurrentViewName(null);
212             setCurrentViewUid(null);
213             throw e;
214         }
215     }
216     
217     protected void includeRootPage() throws Exception {
218         String viewName = getPreViewMappings().containsKey("root") ? (String) preViewMappings.get("root") : "root";
219         include("root", viewName);
220     }
221     
222     protected void include(String uid, String viewName) throws Exception {
223         Model model = null;
224         
225         try {
226             model = resolveModel(viewName);
227         }
228         catch(AccessControlException ace) {
229             ace.printStackTrace();
230             renderView("accessdenied", null);
231             return;
232         }
233         
234         model.service();
235         
236         Map params = getHttpServletRequest().getParameterMap();
237         Set keys = params.keySet();
238         if(keys.size() > 0) {
239             for (Iterator iter = keys.iterator(); iter.hasNext();) {
240                 String key = (String) iter.next();
241                 
242                 if(!key.startsWith(viewName)) continue;
243                 
244                 String tmp[] = key.split("//.");
245                 
246                 String value[] = (String[]) params.get(key);
247                 
248                 if(value.length == 1) model.setStatefulAttribute(tmp[tmp.length-1], value[0]);
249                 else model.setStatefulAttribute(tmp[tmp.length-1], value);
250             }
251         }
252         
253         viewName = viewName.replace('.', '/');
254         renderView(viewName, model);        
255     }
256     
257     
258     
259     protected void renderView(String viewName, Model model) throws Exception {
260         Map tmp = new HashMap(5);
261         tmp.put("layout", getLayoutViewManager());
262         tmp.put("link", getLinkViewManager());
263         tmp.put("action", getActionViewManager());
264         
265         Map tmp2 = new HashMap(2);
266         if(model != null) {
267             tmp2.putAll(model.getStatefulAttributeMap());
268             tmp2.putAll(model.getStatelessAttributeMap());
269             tmp.put("attributes", tmp2);
270         }
271         
272         tmp.put("acl", getAccessController());       
273         
274         ViewResolver viewResolver = getViewResolver();        
275         viewResolver.resolveViewName(viewName, null).render(tmp, getHttpServletRequest(), getHttpServletResponse());        
276     }
277     
278     
279     private Model resolveModel(String modelName) throws Exception {    
280 
281         Class modelClass = (Class) modelClasses.get(modelName);
282         Model model;
283         if(modelClass == null) modelClass = Class.forName("net.sf.fridaymvc.models.BasicModel");
284         
285         AccessRoleAttribute rr = (AccessRoleAttribute) Attributes.getAttribute(modelClass, AccessRoleAttribute.class);
286         if(rr != null && !getAccessController().hasRole(rr.getName())) {
287             throw new AccessControlException("User don't have required role: " + rr.getName());            
288         }
289                
290         AccessPermissionAttribute rp = (AccessPermissionAttribute) Attributes.getAttribute(modelClass, AccessPermissionAttribute.class);
291         if(rp != null && !getAccessController().hasPermission(rp.getName())) throw new AccessControlException("User don't have required permission: " + rp.getName());
292         
293         AccessLoggedAttribute rl = (AccessLoggedAttribute) Attributes.getAttribute(modelClass, AccessLoggedAttribute.class);
294         if(rl != null && getUser() == null) throw new AccessControlException("User hasn't logged");
295         
296         model = (Model) modelClass.newInstance();        
297         
298         return model;
299     }
300 
301     /***
302      * @return Returns the httpServletRequest.
303      */
304     public HttpServletRequest getHttpServletRequest() {
305         return (HttpServletRequest) this.httpServletRequest.get();
306     }
307     /***
308      * @param httpServletRequest The httpServletRequest to set.
309      */
310     public  void setHttpServletRequest(HttpServletRequest httpServletRequest) {
311         this.httpServletRequest.set(httpServletRequest);
312     }
313     /***
314      * @return Returns the httpServletResponse.
315      */
316     public HttpServletResponse getHttpServletResponse() {
317         return (HttpServletResponse) this.httpServletResponse.get();
318     }
319     /***
320      * @param httpServletResponse The httpServletResponse to set.
321      */
322     public void setHttpServletResponse(HttpServletResponse httpServletResponse) {
323         this.httpServletResponse.set(httpServletResponse);
324     }    
325     /***
326      * @return Returns the preViewMappings.
327      */
328     public Map getPreViewMappings() {
329         if(this.preViewMappings == null) {
330             synchronized(this) {
331                 if(this.preViewMappings == null) {
332                     setPreViewMappings(Collections.unmodifiableMap(Collections.EMPTY_MAP));
333                 }
334             }
335         }
336         return this.preViewMappings;
337     }
338     /***
339      * @param preViewMappings The preViewMappings to set.
340      */
341     public void setPreViewMappings(Map viewMappings) {
342         this.preViewMappings = viewMappings;
343     }
344     /***
345      * @return Returns the viewResolver.
346      */
347     public ViewResolver getViewResolver() {
348         if(this.viewResolver == null) {
349             synchronized(this) {
350                 if(this.viewResolver == null) {
351                     setViewResolver((ViewResolver) getWebApplicationContext().getBean("viewResolver", ViewResolver.class));
352                 }
353             }
354         }
355         return this.viewResolver;
356     }
357     /***
358      * @param viewResolver The viewResolver to set.
359      */
360     public void setViewResolver(ViewResolver viewResolver) {
361         this.viewResolver = viewResolver;
362     }
363     
364     /***
365      * @return Returns the webApplicationContext.
366      */
367     public WebApplicationContext getWebApplicationContext() {
368         return this.webApplicationContext;
369     }
370     
371     /***
372      * @param webApplicationContext The webApplicationContext to set.
373      */
374     public void setApplicationContext(WebApplicationContext webApplicationContext) {
375         this.webApplicationContext = webApplicationContext;
376     }
377     
378     /***
379      * @return Returns the layoutViewManager.
380      */
381     public LayoutViewManager getLayoutViewManager() {
382         if(this.layoutViewManager == null) {
383             synchronized(this) {
384                 if(this.layoutViewManager == null) {
385                     this.layoutViewManager = new LayoutViewManager();
386                 }
387             }
388         }
389         return this.layoutViewManager;
390     }
391     /***
392      * @param layoutViewManager The layoutViewManager to set.
393      */
394     public void setLayoutViewManager(LayoutViewManager layoutViewManager) {
395         this.layoutViewManager = layoutViewManager;
396     }
397     /***
398      * @return Returns the linkViewManager.
399      */
400     public LinkViewManager getLinkViewManager() {
401         if(this.linkViewManager == null) {
402             synchronized(this) {
403                 if(this.linkViewManager == null) {
404                     setLinkViewManager(new LinkViewManager());
405                 }
406             }
407         }
408         return this.linkViewManager;
409     }
410     /***
411      * @param linkViewManager The linkViewManager to set.
412      */
413     public void setLinkViewManager(LinkViewManager linkViewManager) {
414         this.linkViewManager = linkViewManager;
415     }
416 
417 
418     /***
419      * @return Returns the actionViewManager.
420      */
421     public ActionViewManager getActionViewManager() {
422         if(this.actionViewManager == null) {
423             synchronized(this) {
424                 if(this.actionViewManager == null) {
425                     setActionViewManager(new ActionViewManager());
426                 }
427             }
428         }
429         return this.actionViewManager;
430     }
431     /***
432      * @param actionViewManager The actionViewManager to set.
433      */
434     public void setActionViewManager(ActionViewManager actionViewManager) {
435         this.actionViewManager = actionViewManager;
436     }
437     
438     public StringBuffer getRelativeServletPath() {
439         HttpServletRequest req = getHttpServletRequest();
440         StringBuffer sb = new StringBuffer(req.getContextPath());
441         sb.append(req.getServletPath());
442         return sb;
443     }
444     /***
445      * @return Returns the parameters.
446      */
447     public Parameters getParameters() {
448         if(this.parameters == null) {
449             synchronized(this) {
450                 if(this.parameters == null) {
451                     setParameters(new Parameters());
452                 }
453             }
454         }
455         return this.parameters;
456     }
457     /***
458      * @param parameters The parameters to set.
459      */
460     public void setParameters(Parameters parameters) {
461         this.parameters = parameters;
462     }
463     /***
464      * @return Returns the viewMapping.
465      */
466     public Map getViewMapping() {
467         if(this.viewMapping == null) {
468             synchronized(this) {
469                 if(this.viewMapping == null) {
470                     setViewMapping(new HashMap(1));
471                 }
472             }
473         }
474         return this.viewMapping;
475     }
476     /***
477      * @param viewMapping The viewMapping to set.
478      */
479     public void setViewMapping(Map viewMapping) {
480         this.viewMapping = viewMapping;
481     }
482 
483 
484     /***
485      * @return Returns the currentViewName.
486      */
487     public String getCurrentViewName() {
488         return (String) this.currentViewName.get();
489     }
490     /***
491      * @param currentViewName The currentViewName to set.
492      */
493     public void setCurrentViewName(String currentViewName) {
494         this.currentViewName.set(currentViewName);
495     }
496     /***
497      * @return Returns the currentViewUid.
498      */
499     public String getCurrentViewUid() {
500         return (String) this.currentViewUid.get();
501     }
502     /***
503      * @param currentViewUid The currentViewUid to set.
504      */
505     public void setCurrentViewUid(String currentViewUid) {
506         this.currentViewUid.set(currentViewUid);
507     }
508     
509     public Object getBean(String id) {
510         return getWebApplicationContext().getBean(id);
511     }
512     
513     public static final RunData getInstance() {
514         return RunData.instance;
515     }
516         
517     /***
518      * @return Returns the user.
519      */
520     public User getUser() {
521         return (User) getHttpServletRequest().getSession().getAttribute("user");
522     }
523     /***
524      * @param user The user to set.
525      */
526     public void setUser(User user) {
527         getHttpServletRequest().getSession().setAttribute("user", user);
528     }
529     /***
530      * @return Returns the accessController.
531      */
532     public AccessController getAccessController() {
533         if(this.accessController == null) {
534             synchronized(this) {
535                 if(this.accessController == null) {
536                     setAccessController(new AccessController());
537                 }
538             }
539         }
540         return this.accessController;
541     }
542     
543     /***
544      * @param accessController The accessController to set.
545      */
546     public void setAccessController(AccessController accessController) {
547         this.accessController = accessController;
548     }    
549     
550     /***
551      * @return Returns the currentAction.
552      */
553     public Action getCurrentAction() {
554         return (Action) getHttpServletRequest().getAttribute("currentAction");
555     }
556     /***
557      * @param currentAction The currentAction to set.
558      */
559     public void setCurrentAction(Action currentAction) {                  
560         getHttpServletRequest().setAttribute("currentAction", currentAction);        
561     }
562 
563     /* (non-Javadoc)
564      * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
565      */
566     public void setApplicationContext(ApplicationContext arg0) throws BeansException {
567         this.webApplicationContext = (WebApplicationContext) arg0;
568     }
569 }