Source Code Cross Referenced for MethodCacheInterceptor.java in  » ERP-CRM-Financial » Kuali-Financial-System » org » kuali » core » util » cache » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » Kuali Financial System » org.kuali.core.util.cache 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2004 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         * 
016:         * Code obtained from http://opensource.atlassian.com/confluence/spring/display/DISC/Caching+the+result+of+methods+using+Spring+and+EHCache
017:         * and modified for use within Kuali
018:         */
019:
020:        // begin Kuali Foundation modification
021:        package org.kuali.core.util.cache;
022:
023:        // Kuali Foundation modification: changed some imports
024:        import java.io.Serializable;
025:
026:        import org.aopalliance.intercept.MethodInterceptor;
027:        import org.aopalliance.intercept.MethodInvocation;
028:        import org.apache.commons.logging.Log;
029:        import org.apache.commons.logging.LogFactory;
030:        import org.kuali.core.util.CopiedObject;
031:        import org.kuali.core.util.ObjectUtils;
032:        import org.springframework.beans.factory.InitializingBean;
033:        import org.springframework.util.Assert;
034:
035:        import com.opensymphony.oscache.base.Cache;
036:        import com.opensymphony.oscache.base.NeedsRefreshException;
037:
038:        /**
039:         * begin Kuali Foundation modification
040:         * This class implements org.aopalliance.intercept.MethodInterceptor. This interceptor builds the cache key for the method and
041:         * checks if an earlier result was cached with that key. If so, the cached result is returned; otherwise, the intercepted method is
042:         * called and the result cached for future use.
043:         * end Kuali Foundation modification
044:         * 
045:         * @author Kuali Rice Team (kuali-rice@googlegroups.com)
046:         * @since 2004.10.07
047:         */
048:        public class MethodCacheInterceptor implements  MethodInterceptor,
049:                InitializingBean {
050:            private static final Log LOG = LogFactory
051:                    .getLog(MethodCacheInterceptor.class);
052:
053:            private Cache cache;
054:            // begin Kuali Foundation modification
055:            private int expirationTimeInSeconds = 1000;
056:            private long maxEntrySizeInBytes = 0;
057:
058:            // end Kuali Foundation modification
059:
060:            /**
061:             * begin Kuali Foundation modification
062:             * @param cache name of cache to be used
063:             * end Kuali Foundation modification
064:             */
065:            public void setCache(Cache cache) {
066:                this .cache = cache;
067:            }
068:
069:            // begin Kuali Foundation modification
070:            /**
071:             * Entries older than this will have their contents replaced by the return value from a call to the appropriate method
072:             * 
073:             * @param expirationTimeInSeconds
074:             */
075:            public void setExpirationTimeInSeconds(int expirationTimeInSeconds) {
076:                this .expirationTimeInSeconds = expirationTimeInSeconds;
077:            }
078:
079:            /**
080:             * Entries whose size is larger than the current value will not be cached. If the maxEntrySizeInBytes <= 0, no size limit will
081:             * be applied.
082:             * 
083:             * @param maxEntrySizeInBytes
084:             */
085:            public void setMaxEntrySizeInBytes(long maxEntrySizeInBytes) {
086:                this .maxEntrySizeInBytes = maxEntrySizeInBytes;
087:            }
088:
089:            // end Kuali Foundation modification
090:
091:            /**
092:             * Checks if required attributes are provided.
093:             * 
094:             * begin Kuali Foundation modification
095:             * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
096:             * end Kuali Foundation modification
097:             */
098:            public void afterPropertiesSet() throws Exception {
099:                Assert
100:                        .notNull(cache,
101:                                "A cache is required. Use setCache(Cache) to provide one.");
102:            }
103:
104:            /**
105:             * begin Kuali Foundation modification
106:             * Caches method results, if possible.
107:             * <p>
108:             * Results must be Serializable to be cached. Method with unSerializable results will never have their results cached, and will
109:             * log error messages complaining about that fact.
110:             * 
111:             * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
112:             * end Kuali Foundation modification
113:             */
114:            public Object invoke(MethodInvocation invocation) throws Throwable {
115:                // begin Kuali Foundation modification
116:                boolean cancelUpdate = true;
117:
118:                Object methodResult = null;
119:                String cacheKey = buildCacheKey(invocation);
120:
121:                // lookup result in cache
122:                if (LOG.isTraceEnabled()) {
123:                    LOG.trace("looking for method result for invocation '"
124:                            + cacheKey + "'");
125:                }
126:                try {
127:                    CopiedObject cachedEntry = (CopiedObject) cache
128:                            .getFromCache(cacheKey, expirationTimeInSeconds);
129:                    if (LOG.isDebugEnabled()) {
130:                        LOG
131:                                .debug("using cached result deepCopy for invocation '"
132:                                        + cacheKey + "'");
133:                    }
134:
135:                    // really expensive hack to try to keep from returning direct references to modifiable cached values
136:                    // because if you return a direct reference to a cached value to someone, and it is of a mutable type, any changes they
137:                    // make to what seems like "their copy" will also be reflected in the cached value, which is a Really Bad Thing
138:                    methodResult = ObjectUtils.deepCopy(cachedEntry
139:                            .getContent());
140:                    cancelUpdate = false;
141:                } catch (NeedsRefreshException e) {
142:                    // call intercepted method
143:                    try {
144:                        if (LOG.isTraceEnabled()) {
145:                            LOG
146:                                    .trace("calling intercepted method for invocation '"
147:                                            + cacheKey + "'");
148:                        }
149:                        methodResult = invocation.proceed();
150:                    } catch (Exception invocationException) {
151:                        LOG
152:                                .warn("unable to cache methodResult: caught exception invoking intercepted method: '"
153:                                        + invocationException);
154:                        throw invocationException;
155:                    }
156:
157:                    // cache method result, if possible
158:                    // there's no way to tell whether a result is cacheable until after the method gets called,
159:                    // since methods may hand back a Serializable object even if the method is declared to return
160:                    // a more general nonSerializable type (e.g. List is not Serializable, but if the method
161:                    // actually returns ArrayList instances, they are)
162:                    //
163:                    // nulls are a special case, since isAssignableFrom will never return true, yet they are
164:                    // Serializable (at least for this kind of use)
165:                    //
166:                    // caching a deepCopy of the methodResult to prevent someone changing the cached value directly,
167:                    // through a shared reference
168:                    if ((methodResult == null)
169:                            || (Serializable.class
170:                                    .isAssignableFrom(methodResult.getClass()))) {
171:                        try {
172:                            CopiedObject cacheCopy = ObjectUtils
173:                                    .deepCopyForCaching((Serializable) methodResult);
174:
175:                            CopiedObject oldContent = (CopiedObject) e
176:                                    .getCacheContent();
177:                            if (oldContent != null) {
178:                                cacheCopy.setOldSize(oldContent.getSize());
179:                            }
180:
181:                            // if no size limit, or under size limit, add to cache
182:                            if ((maxEntrySizeInBytes <= 0)
183:                                    || (cacheCopy.getSize() <= maxEntrySizeInBytes)) {
184:                                if (LOG.isTraceEnabled()) {
185:                                    LOG
186:                                            .trace("caching results for invocation '"
187:                                                    + cacheKey + "'");
188:                                }
189:                                cache.putInCache(cacheKey, cacheCopy);
190:
191:                                // adding, not updating
192:                                cancelUpdate = false;
193:                            } else {
194:                                if (LOG.isTraceEnabled()) {
195:                                    LOG
196:                                            .trace("rejecting oversized methodResult ("
197:                                                    + cacheCopy.getSize()
198:                                                    + " bytes) for invocation '"
199:                                                    + cacheKey + "'");
200:                                }
201:
202:                                // size limit exceeded: remove existing (expired) cache entry, if any
203:                                if (oldContent != null) {
204:                                    if (LOG.isTraceEnabled()) {
205:                                        LOG
206:                                                .trace("flushing previous value for oversized invocation '"
207:                                                        + cacheKey + "'");
208:                                    }
209:
210:                                    cache.cancelUpdate(cacheKey);
211:                                    cache.flushEntry(cacheKey);
212:
213:                                    // already canceled the update, don't need to cancel the update again
214:                                    cancelUpdate = false;
215:                                }
216:                            }
217:                        } catch (Exception cacheException) {
218:                            LOG
219:                                    .error("unable to cache methodResult: caught exception invoking putInCache: '"
220:                                            + cacheException);
221:                            throw cacheException;
222:                        }
223:                    } else {
224:                        LOG
225:                                .error("unable to cache nonSerializable result type for invocation '"
226:                                        + cacheKey + "'");
227:                    }
228:                } finally {
229:                    // it is imperative that you call cancelUpdate if you aren't going to update the cache entry
230:                    if (cancelUpdate) {
231:                        cache.cancelUpdate(cacheKey);
232:                    }
233:                }
234:
235:                return methodResult;
236:                // end Kuali Foundation modification
237:            }
238:
239:            // begin Kuali Foundation modification
240:            /**
241:             * @param invocation MethodInvocation being handled
242:             * @return cache key: className.methodName(paramClass=argValue[,paramClass=argValue...])
243:             */
244:            private String buildCacheKey(MethodInvocation invocation) {
245:                return buildCacheKey(invocation.getStaticPart().toString(),
246:                        invocation.getArguments());
247:            }
248:
249:            /**
250:             * @param className
251:             * @param methodName
252:             * @param paramTypes
253:             * @param argValues
254:             * @return cache key: className.methodName(paramClass=argValue[,paramClass=argValue...])
255:             */
256:            public String buildCacheKey(String methodSignature,
257:                    Object[] argValues) {
258:                StringBuffer cacheKey = new StringBuffer(methodSignature);
259:                cacheKey.append(": ");
260:                if (argValues != null) {
261:                    for (int i = 0; i < argValues.length; i++) {
262:                        if (i > 0) {
263:                            cacheKey.append(",");
264:                        }
265:                        // handle weird cache bug:
266:                        // if you call a one-arg method foo with a null arg i.e. foo(null),
267:                        // and then call it with an argument whose toString evaluates to "null",
268:                        // OSCache gets stuck in an infinite wait() call because it somehow thinks
269:                        // another thread is already updating this cache entry
270:                        //
271:                        // workaround: change so that args which are actually null literal have
272:                        // some weird, unlikely-to-be-encountered String representation
273:                        if (argValues[i] == null) {
274:                            cacheKey.append("<literal null>");
275:                        } else {
276:                            cacheKey.append(argValues[i]);
277:                        }
278:                    }
279:                }
280:                return cacheKey.toString();
281:            }
282:
283:            /**
284:             * @param key
285:             * @return true if the cache contains an entry with the given key
286:             */
287:            public boolean containsCacheKey(String key) {
288:                boolean contains = false;
289:
290:                try {
291:                    cache.getFromCache(key);
292:                    contains = true;
293:                } catch (NeedsRefreshException e) {
294:                    // it is imperative that you call cancelUpdate if you aren't going to update the cache entry that caused the
295:                    // NeedsRefreshException above
296:                    cache.cancelUpdate(key);
297:                    contains = false;
298:                }
299:
300:                return contains;
301:            }
302:
303:            /** 
304:             * Removes a method cache if one exists for the given key.
305:             * @param cacheKey - key for method signature and parameters - see buildCacheKey
306:             */
307:            public void removeCacheKey(String cacheKey) {
308:                if (!containsCacheKey(cacheKey)) {
309:                    return;
310:                }
311:
312:                LOG.debug("removing method cache for key: " + cacheKey);
313:                cache.cancelUpdate(cacheKey);
314:                cache.flushEntry(cacheKey);
315:            }
316:
317:            // Kuali Foundation modification: removed getCacheKey(String, String, Object[])
318:            // end Kuali Foundation modification
319:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.