View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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  package org.kuali.rice.core.web.cache;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.Comparator;
21  import java.util.List;
22  
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  
26  import org.kuali.rice.core.api.cache.CacheManagerRegistry;
27  import org.kuali.rice.core.api.util.tree.Node;
28  import org.kuali.rice.core.api.util.tree.Tree;
29  import org.kuali.rice.core.impl.services.CoreImplServiceLocator;
30  import org.kuali.rice.krad.util.GlobalVariables;
31  import org.kuali.rice.krad.web.controller.UifControllerBase;
32  import org.kuali.rice.krad.web.form.UifFormBase;
33  import org.springframework.cache.CacheManager;
34  import org.springframework.stereotype.Controller;
35  import org.springframework.validation.BindingResult;
36  import org.springframework.web.bind.annotation.ModelAttribute;
37  import org.springframework.web.bind.annotation.RequestMapping;
38  import org.springframework.web.bind.annotation.RequestMethod;
39  import org.springframework.web.servlet.ModelAndView;
40  
41  @Controller
42  @RequestMapping(value = "/core/admin/cache")
43  public class CacheAdminController extends UifControllerBase {
44  
45      private CacheManagerRegistry registry;
46  
47      public synchronized CacheManagerRegistry getRegistry() {
48          if (registry == null) {
49              registry = CoreImplServiceLocator.getCacheManagerRegistry();
50          }
51          return registry;
52      }
53  
54      /**
55       * @see org.kuali.rice.krad.web.controller.UifControllerBase#createInitialForm(javax.servlet.http.HttpServletRequest)
56       */
57      @Override
58      protected CacheAdminForm createInitialForm(HttpServletRequest request) {
59          return new CacheAdminForm();
60      }
61  
62      @Override
63  	@RequestMapping(params = "methodToCall=start")
64  	public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
65  			HttpServletRequest request, HttpServletResponse response) {
66  
67          final Tree<String, String> cacheTree = new Tree<String,String>();
68  
69          final Node<String,String> root = new Node<String,String>("Root", "Root");
70          final List<CacheManager> cms = new ArrayList<CacheManager>(getRegistry().getCacheManagers());
71          Collections.sort(cms, new ByName());
72  
73          for (final CacheManager cm : cms) {
74              final String name = getRegistry().getCacheManagerName(cm);
75              final Node<String, String> cmNode = new Node<String, String>(name, name);
76              final List<String> names = new ArrayList<String>(cm.getCacheNames());
77              Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
78  
79              for (final String cn : names) {
80                  final Node<String, String> cNode = new Node<String, String>(cn, cn);
81                  //no way to get a keySet from the cache w/o calling the nativeCache
82                  //method which is a bad idea b/c it will tie the rice codebase to
83                  //a caching implementation
84                  cmNode.addChild(cNode);
85              }
86  
87              root.addChild(cmNode);
88          }
89  
90          cacheTree.setRootElement(root);
91          ((CacheAdminForm) form).setCacheTree(cacheTree);
92  
93          return super.start(form, result, request, response);
94      }
95  
96  	@RequestMapping(params = "methodToCall=flush", method = RequestMethod.POST)
97  	public ModelAndView flush(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
98  			HttpServletRequest request, HttpServletResponse response) {
99  
100         //FIXME: Could optimize this such that specific cache flushes don't execute if a complete CacheManager
101         //flush was requested
102         for (String name : ((CacheAdminForm) form).getFlush()) {
103             //path == cacheManager index, cache index
104             final List<Integer> path = path(removePrefix(name));
105             final Tree<String, String> tree = ((CacheAdminForm) form).getCacheTree();
106             final Integer cmIdx = path.get(0);
107             final Node<String, String> cmNode = tree.getRootElement().getChildren().get(cmIdx);
108             final String cmName = cmNode.getData();
109             final CacheManager cm = getRegistry().getCacheManager(cmName);
110 
111             if (path.size() == 1) {
112                 flushAllCaches(cm);
113                 GlobalVariables.getMessageMap().putInfoForSectionId("mainGroup_div","flush.all.cachemanager", cmName);
114             } else {
115                 final Integer cIdx = path.get(1);
116                 final Node<String, String> cNode = cmNode.getChildren().get(cIdx);
117                 final String cName = cNode.getData();
118                 flushSpecificCache(cm, cName);
119                 GlobalVariables.getMessageMap().putInfoForSectionId("mainGroup_div",
120                         "flush.single.cachemanager", cName, cmName);
121             }
122         }
123         return super.start(form, result, request, response);
124     }
125 
126     private static void flushSpecificCache(CacheManager cm, String cache) {
127         for (String s : cm.getCacheNames()) {
128             if (cache.equals(s)) {
129                  cm.getCache(s).clear();
130                  return;
131             }
132         }
133     }
134 
135     private static void flushAllCaches(CacheManager cm) {
136         for (String s : cm.getCacheNames()) {
137             cm.getCache(s).clear();
138         }
139     }
140 
141     // given: 35_node_2_parent_node_0_parent_root will remove "35_"
142     private static String removePrefix(String s) {
143         final StringBuilder sbn = new StringBuilder(s);
144         sbn.delete(0, sbn.indexOf("_") + 1);
145         return sbn.toString();
146     }
147 
148     // given: node_2_parent_node_0_parent_root will return {0, 2}
149     private static List<Integer> path(String s) {
150         final String[] path = s.split("_parent_");
151         final List<Integer> pathIdx = new ArrayList<Integer>();
152         //ignore length - 2 to ignore root
153         for (int i = path.length - 2; i >= 0; i--) {
154             pathIdx.add(Integer.valueOf(path[i].substring(5)));
155         }
156         return Collections.unmodifiableList(pathIdx);
157     }
158 
159     private final class ByName implements Comparator<CacheManager> {
160 
161         @Override
162         public int compare(CacheManager o1, CacheManager o2) {
163             return String.CASE_INSENSITIVE_ORDER.compare(getRegistry().getCacheManagerName(o1),
164                     getRegistry().getCacheManagerName(o2));
165         }
166     }
167 
168 }