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 SearchParamInfo firstParam = params.get(0);
68 if (firstParam.getKey().equals("lu.queryParam.cluVersionIndId")) {
69 doIdTranslation(searchResult);
70 }
71 }
72 return searchResult;
73 } catch (Exception ex) {
74
75 ex.printStackTrace();
76 throw new RuntimeException(ex);
77 }
78 }
79
80 @Override
81 public SearchResultInfo cachingSearch(SearchRequestInfo searchRequest) {
82 try
83 {
84 String cacheKey = searchRequest.toString();
85 if (cachingEnabled) {
86
87
88 MaxAgeSoftReference<SearchResultInfo> ref = searchCache.get(cacheKey);
89 if (ref != null) {
90 SearchResultInfo cachedSearchResult = ref.get();
91 if (cachedSearchResult != null) {
92 return cachedSearchResult;
93 }
94 }
95 }
96
97
98 SearchResultInfo searchResult = search(searchRequest);
99
100 if (cachingEnabled) {
101
102 searchCache
103 .put(cacheKey, new MaxAgeSoftReference<SearchResultInfo>(searchCacheMaxAgeSeconds, searchResult));
104 }
105
106 return searchResult;
107 } catch (Exception ex) {
108
109 ex.printStackTrace();
110 throw new RuntimeException(ex);
111 }
112 }
113
114 private void doIdTranslation(SearchResultInfo searchResult) {
115 for (SearchResultRowInfo searchResultRow : searchResult.getRows()) {
116 for (SearchResultCellInfo searchResultCell : searchResultRow.getCells()) {
117 String value = searchResultCell.getValue();
118 if (value != null && value.startsWith("kuali.atp")) {
119 String newValue = idTranslatorFilter.getTranslationForAtp(value, ContextUtils.getContextInfo());
120 if (newValue != null) {
121 searchResultCell.setValue(newValue);
122 }
123 }
124 }
125 }
126 }
127
128 @Override
129 public void afterPropertiesSet() throws Exception {
130 if(cachingEnabled){
131 searchCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<SearchResultInfo>>( searchCacheMaxSize ) );
132 }
133 }
134
135 public void setSearchDispatcher(SearchService searchDispatcher) {
136 this.searchDispatcher = searchDispatcher;
137 }
138
139 public void setIdTranslatorFilter(IdTranslatorFilter idTranslatorFilter) {
140 this.idTranslatorFilter = idTranslatorFilter;
141 }
142
143 public void setCachingEnabled(boolean cachingEnabled) {
144 this.cachingEnabled = cachingEnabled;
145 }
146
147 public void setSearchCacheMaxSize(int searchCacheMaxSize) {
148 this.searchCacheMaxSize = searchCacheMaxSize;
149 }
150
151 public void setSearchCacheMaxAgeSeconds(int searchCacheMaxAgeSeconds) {
152 this.searchCacheMaxAgeSeconds = searchCacheMaxAgeSeconds;
153 }
154
155
156
157
158
159
160
161
162 public class MaxAgeSoftReference<T> extends SoftReference<T> {
163
164 private long expires;
165
166 public MaxAgeSoftReference(long expires, T referent) {
167 super(referent);
168 this.expires = System.currentTimeMillis() + expires * 1000;
169 }
170
171 public boolean isValid() {
172 return System.currentTimeMillis() < expires;
173 }
174
175 public T get() {
176 return isValid() ? super.get() : null;
177 }
178
179 }
180
181
182
183
184
185 public class MaxSizeMap<K,V> extends LinkedHashMap<K,V> {
186 private static final long serialVersionUID = -5354227348838839919L;
187
188 private int maxSize;
189
190
191
192
193 public MaxSizeMap( int maxSize ) {
194 this( maxSize, false );
195 }
196
197
198
199
200 public MaxSizeMap( int maxSize, boolean accessOrder ) {
201 super( maxSize / 2, 0.75f, accessOrder );
202 this.maxSize = maxSize;
203 }
204
205
206
207
208 @Override
209 protected boolean removeEldestEntry(Entry<K,V> eldest) {
210 return size() > maxSize;
211 }
212
213 }
214 }