1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.core.web.cache;
17
18 import org.kuali.rice.core.api.cache.CacheManagerRegistry;
19 import org.kuali.rice.core.api.util.tree.Node;
20 import org.kuali.rice.core.api.util.tree.Tree;
21 import org.kuali.rice.core.impl.services.CoreImplServiceLocator;
22 import org.kuali.rice.kim.api.KimConstants;
23 import org.kuali.rice.kim.api.identity.Person;
24 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
25 import org.kuali.rice.krad.util.GlobalVariables;
26 import org.kuali.rice.krad.util.KRADConstants;
27 import org.kuali.rice.krad.web.controller.UifControllerBase;
28 import org.kuali.rice.krad.web.form.UifFormBase;
29 import org.springframework.cache.CacheManager;
30 import org.springframework.stereotype.Controller;
31 import org.springframework.validation.BindingResult;
32 import org.springframework.web.bind.annotation.ModelAttribute;
33 import org.springframework.web.bind.annotation.RequestMapping;
34 import org.springframework.web.bind.annotation.RequestMethod;
35 import org.springframework.web.servlet.ModelAndView;
36
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39 import java.lang.reflect.InvocationTargetException;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.Comparator;
43 import java.util.List;
44
45 @Controller
46 @RequestMapping(value = "/core/admin/cache")
47 public class CacheAdminController extends UifControllerBase {
48
49 private CacheManagerRegistry registry;
50
51 public synchronized CacheManagerRegistry getRegistry() {
52 if (registry == null) {
53 registry = CoreImplServiceLocator.getCacheManagerRegistry();
54 }
55 return registry;
56 }
57
58
59
60
61 @Override
62 protected CacheAdminForm createInitialForm() {
63 return new CacheAdminForm();
64 }
65
66 @Override
67 @RequestMapping(params = "methodToCall=start")
68 public ModelAndView start(UifFormBase form) {
69
70 final Tree<String, String> cacheTree = new Tree<String,String>();
71
72 final Node<String,String> root = new Node<String,String>("Root", "Root");
73 final List<CacheManager> cms = new ArrayList<CacheManager>(getRegistry().getCacheManagers());
74 Collections.sort(cms, new ByName());
75
76 for (final CacheManager cm : cms) {
77 final String name = getRegistry().getCacheManagerName(cm);
78 final Node<String, String> cmNode = new Node<String, String>(name, name);
79 final List<String> names = new ArrayList<String>(cm.getCacheNames());
80 Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
81
82 for (final String cn : names) {
83 String cacheSize = getCacheSize(name, cn);
84 final Node<String, String> cNode = new Node<String, String>(cn, cn + (cacheSize != null ? " - " + cacheSize : ""));
85
86
87
88 cmNode.addChild(cNode);
89 }
90
91 root.addChild(cmNode);
92 }
93
94 cacheTree.setRootElement(root);
95 ((CacheAdminForm) form).setCacheTree(cacheTree);
96
97 return super.start(form);
98 }
99
100 @RequestMapping(params = "methodToCall=flush", method = RequestMethod.POST)
101 public ModelAndView flush(UifFormBase form) {
102 Person user = GlobalVariables.getUserSession().getPerson();
103 boolean isAuthorized = KimApiServiceLocator.getPermissionService().isAuthorized(
104 user.getPrincipalId(),
105 KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE,
106 KRADConstants.USE_CACHE_ADMINISTRATION_SCREEN,
107 Collections.singletonMap(KimConstants.AttributeConstants.PRINCIPAL_ID, user.getPrincipalId()));
108 if(isAuthorized){
109
110
111
112 for (String name : ((CacheAdminForm) form).getFlush()) {
113
114 final List<Integer> path = path(removePrefix(name));
115 final Tree<String, String> tree = ((CacheAdminForm) form).getCacheTree();
116 final Integer cmIdx = path.get(0);
117 final Node<String, String> cmNode = tree.getRootElement().getChildren().get(cmIdx);
118 final String cmName = cmNode.getData();
119 final CacheManager cm = getRegistry().getCacheManager(cmName);
120
121 if (path.size() == 1) {
122 flushAllCaches(cm);
123 GlobalVariables.getMessageMap().putInfoForSectionId("mainGroup_div","flush.all.cachemanager", cmName);
124 } else {
125 final Integer cIdx = path.get(1);
126 final Node<String, String> cNode = cmNode.getChildren().get(cIdx);
127 final String cName = cNode.getData();
128 flushSpecificCache(cm, cName);
129 GlobalVariables.getMessageMap().putInfoForSectionId("mainGroup_div",
130 "flush.single.cachemanager", cName, cmName);
131 }
132 }
133 }else{
134 GlobalVariables.getMessageMap().putError("flush","error.authorization.general",user.getPrincipalName(),"flush","cachemanager");
135 }
136 return super.start(form);
137 }
138
139 private static void flushSpecificCache(CacheManager cm, String cache) {
140 for (String s : cm.getCacheNames()) {
141 if (cache.equals(s)) {
142 cm.getCache(s).clear();
143 return;
144 }
145 }
146 }
147
148 private static void flushAllCaches(CacheManager cm) {
149 for (String s : cm.getCacheNames()) {
150 cm.getCache(s).clear();
151 }
152 }
153
154
155 private static String removePrefix(String s) {
156 final StringBuilder sbn = new StringBuilder(s);
157 sbn.delete(0, sbn.indexOf("_") + 1);
158 return sbn.toString();
159 }
160
161
162 private static List<Integer> path(String s) {
163 final String[] path = s.split("_parent_");
164 final List<Integer> pathIdx = new ArrayList<Integer>();
165
166 for (int i = path.length - 2; i >= 0; i--) {
167 pathIdx.add(Integer.valueOf(path[i].substring(5)));
168 }
169 return Collections.unmodifiableList(pathIdx);
170 }
171
172
173
174
175
176 private String getCacheSize(String cacheManagerName, String cacheName) {
177 Object nativeCache = getRegistry().getCacheManager(cacheManagerName).getCache(cacheName).getNativeCache();
178 try {
179 Class<?> ehcache = Class.forName("net.sf.ehcache.Cache");
180 if (ehcache.isInstance(nativeCache)) {
181 Object intSize = ehcache.getDeclaredMethod("getSize").invoke(nativeCache);
182 if (intSize != null) {
183 return intSize.toString();
184 }
185 }
186 } catch (ClassNotFoundException e) {
187
188 } catch (NoSuchMethodException e) {
189
190 } catch (InvocationTargetException e) {
191
192 } catch (IllegalAccessException e) {
193
194 }
195 return null;
196 }
197
198 private final class ByName implements Comparator<CacheManager> {
199
200 @Override
201 public int compare(CacheManager o1, CacheManager o2) {
202 return String.CASE_INSENSITIVE_ORDER.compare(getRegistry().getCacheManagerName(o1),
203 getRegistry().getCacheManagerName(o2));
204 }
205 }
206
207 }