1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.ui.server.gwt;
17
18 import java.lang.ref.SoftReference;
19 import java.util.Collections;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Map.Entry;
24
25 import org.kuali.student.common.ui.client.service.SearchRpcService;
26 import org.kuali.student.r1.common.assembly.transform.IdTranslatorFilter;
27 import org.kuali.student.r2.common.exceptions.MissingParameterException;
28 import org.kuali.student.r2.core.search.dto.*;
29 import org.kuali.student.r2.core.search.service.SearchService;
30 import org.kuali.student.r2.common.util.ContextUtils;
31 import org.springframework.beans.factory.InitializingBean;
32
33 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
34
35 public class SearchDispatchRpcGwtServlet extends RemoteServiceServlet implements SearchRpcService, InitializingBean {
36
37 private static final long serialVersionUID = 1L;
38
39 private IdTranslatorFilter idTranslatorFilter;
40
41 private SearchService searchDispatcher;
42
43 protected boolean cachingEnabled = false;
44 protected int searchCacheMaxSize = 20;
45 protected int searchCacheMaxAgeSeconds = 90;
46 protected Map<String,MaxAgeSoftReference<SearchResultInfo>> searchCache;
47
48
49 public SearchDispatchRpcGwtServlet() {
50 super();
51 }
52
53
54
55
56
57
58
59
60 @Override
61 public SearchResultInfo search(SearchRequestInfo searchRequest) {
62 try
63 {
64 SearchResultInfo searchResult = searchDispatcher.search(searchRequest, ContextUtils.getContextInfo());
65 List<SearchParamInfo> params = searchRequest.getParams();
66 if (params != null && params.size() > 0) {
67
68 int firstSearchParamInfo = 0 ;
69 SearchParamInfo firstParam = params.get(firstSearchParamInfo);
70 if (firstParam.getKey().equals("lu.queryParam.cluVersionIndId")) {
71 doIdTranslation(searchResult);
72 }
73 }
74 return searchResult;
75 } catch (Exception ex) {
76
77 ex.printStackTrace();
78 throw new RuntimeException(ex);
79 }
80 }
81
82 @Override
83 public SearchResultInfo cachingSearch(SearchRequestInfo searchRequest) {
84 try
85 {
86 String cacheKey = searchRequest.toString();
87 if (cachingEnabled) {
88
89
90 MaxAgeSoftReference<SearchResultInfo> ref = searchCache.get(cacheKey);
91 if (ref != null) {
92 SearchResultInfo cachedSearchResult = ref.get();
93 if (cachedSearchResult != null) {
94 return cachedSearchResult;
95 }
96 }
97 }
98
99
100 SearchResultInfo searchResult = search(searchRequest);
101
102 if (cachingEnabled) {
103
104 searchCache
105 .put(cacheKey, new MaxAgeSoftReference<SearchResultInfo>(searchCacheMaxAgeSeconds, searchResult));
106 }
107
108 return searchResult;
109 } catch (Exception ex) {
110
111 ex.printStackTrace();
112 throw new RuntimeException(ex);
113 }
114 }
115
116 private void doIdTranslation(SearchResultInfo searchResult) {
117 for (SearchResultRowInfo searchResultRow : searchResult.getRows()) {
118 for (SearchResultCellInfo searchResultCell : searchResultRow.getCells()) {
119 String value = searchResultCell.getValue();
120 if (value != null && value.startsWith("kuali.atp")) {
121 String newValue = idTranslatorFilter.getTranslationForAtp(value, ContextUtils.getContextInfo());
122 if (newValue != null) {
123 searchResultCell.setValue(newValue);
124 }
125 }
126 }
127 }
128 }
129
130 @Override
131 public void afterPropertiesSet() throws Exception {
132 if(cachingEnabled){
133 searchCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<SearchResultInfo>>( searchCacheMaxSize ) );
134 }
135 }
136
137 public void setSearchDispatcher(SearchService searchDispatcher) {
138 this.searchDispatcher = searchDispatcher;
139 }
140
141 public void setIdTranslatorFilter(IdTranslatorFilter idTranslatorFilter) {
142 this.idTranslatorFilter = idTranslatorFilter;
143 }
144
145 public void setCachingEnabled(boolean cachingEnabled) {
146 this.cachingEnabled = cachingEnabled;
147 }
148
149 public void setSearchCacheMaxSize(int searchCacheMaxSize) {
150 this.searchCacheMaxSize = searchCacheMaxSize;
151 }
152
153 public void setSearchCacheMaxAgeSeconds(int searchCacheMaxAgeSeconds) {
154 this.searchCacheMaxAgeSeconds = searchCacheMaxAgeSeconds;
155 }
156
157
158
159
160
161
162
163
164 public class MaxAgeSoftReference<T> extends SoftReference<T> {
165
166 private long expires;
167
168 public MaxAgeSoftReference(long expires, T referent) {
169 super(referent);
170 this.expires = System.currentTimeMillis() + expires * 1000;
171 }
172
173 public boolean isValid() {
174 return System.currentTimeMillis() < expires;
175 }
176
177 public T get() {
178 return isValid() ? super.get() : null;
179 }
180
181 }
182
183
184
185
186
187 public class MaxSizeMap<K,V> extends LinkedHashMap<K,V> {
188 private static final long serialVersionUID = -5354227348838839919L;
189
190 private int maxSize;
191
192
193
194
195 public MaxSizeMap( int maxSize ) {
196 this( maxSize, false );
197 }
198
199
200
201
202 public MaxSizeMap( int maxSize, boolean accessOrder ) {
203 super( maxSize / 2, 0.75f, accessOrder );
204 this.maxSize = maxSize;
205 }
206
207
208
209
210 @Override
211 protected boolean removeEldestEntry(Entry<K,V> eldest) {
212 return size() > maxSize;
213 }
214
215 }
216 }