001: package org.enhydra.jdbc.util;
002:
003: import java.util.Hashtable;
004: import java.util.Enumeration;
005: import java.io.FileInputStream;
006: import java.io.DataInputStream;
007: import java.util.regex.Pattern;
008: import java.util.StringTokenizer;
009:
010: import org.enhydra.jdbc.util.Logger;
011:
012: import org.apache.commons.logging.LogFactory;
013:
014: public class RequestCache {
015: // the cache objects
016: // there are only the requests found in the configuration file
017: private static Hashtable cache_ = null;
018:
019: private static Hashtable dsCache_ = null;
020:
021: // all requests , given by the application
022: // be careful, this object may be large, but with a minimum of
023: // object size (only String objects stored in the value part)
024: private static Hashtable requests_ = null;
025:
026: // the current singleton object
027: private static RequestCache theCache_ = null;
028:
029: private long timeToLive_ = 86400000; // 1 day
030:
031: private String path = null;
032:
033: private static Logger logger;
034:
035: /**
036: * This method is used to obtain the cache, if it does not exist, it creates
037: * it
038: */
039: public static synchronized RequestCache getInstance() {
040: if (theCache_ == null) {
041: theCache_ = new RequestCache();
042: }
043: return theCache_;
044: }
045:
046: public static synchronized RequestCache getInstance(String path) {
047: if (theCache_ == null) {
048: theCache_ = new RequestCache(path);
049: }
050: return theCache_;
051: }
052:
053: public RequestCache() {
054: if (logger == null)
055: logger = new Logger(LogFactory
056: .getLog("org.enhydra.jdbc.util"));
057:
058: if (cache_ == null)
059: cache_ = new Hashtable();
060:
061: if (requests_ == null)
062: requests_ = new Hashtable();
063:
064: if (dsCache_ == null)
065: dsCache_ = new Hashtable();
066:
067: readConfigurationFile();
068: }
069:
070: public RequestCache(String path) {
071: if (cache_ == null)
072: cache_ = new Hashtable();
073:
074: if (requests_ == null)
075: requests_ = new Hashtable();
076:
077: this .path = path;
078:
079: readConfigurationFile();
080: }
081:
082: public void readConfigurationFile() {
083: if (path != null) {
084: try {
085: logger
086: .debug("RequestCache: readConfigurationFile try to open file="
087: + path);
088: FileInputStream fstream = new FileInputStream(path);
089: DataInputStream in = new DataInputStream(fstream);
090: logger
091: .debug("RequestCache: readConfigurationFile open done file="
092: + path);
093:
094: while (in.available() != 0) {
095: String req = ((String) in.readLine()).trim();
096: logger
097: .debug("RequestCache:readConfigurationFile line:"
098: + req);
099: if (!req.startsWith("#")) {
100: long ttl = timeToLive_;
101: String newreq = null;
102: if (req.startsWith("ttl")) {
103: StringTokenizer st = new StringTokenizer(
104: req);
105: String ttls = st.nextToken();
106: logger
107: .debug("RequestCache:readConfigurationFile ttls:<"
108: + ttls + ">");
109: ttl = Integer.parseInt(ttls.substring(4));
110: newreq = req.substring(ttls.length())
111: .trim();
112: } else
113: newreq = req;
114:
115: Pattern p = Pattern.compile(newreq);
116: logger
117: .debug("RequestCache:readConfigurationFile newreq:<"
118: + newreq + ">");
119: logger
120: .debug("RequestCache:readConfigurationFile ttl:<"
121: + ttl + ">");
122: RequestCacheObject uco = new RequestCacheObject(
123: newreq, p, ttl);
124: cache_.put(newreq, uco);
125: }
126: }
127:
128: in.close();
129: } catch (Exception e) {
130: System.err.println("File input error");
131: e.printStackTrace();
132: }
133: }
134: }
135:
136: public boolean isInCache(String req) {
137: if (cache_ != null)
138: if (cache_.size() == 0)
139: return false;
140:
141: if ((cache_ == null) || (requests_ == null) || (req == null)
142: || (req.compareTo("") == 0)) {
143: return false;
144: }
145:
146: // optimization for the real life, all application requests
147: // may be found in the requests object, and we need to save time
148: String redir = (String) requests_.get(req);
149: if (redir != null) {
150: if (redir.compareTo("null") != 0) {
151: // logger.debug("RequestCache:isInCache requests_
152: // contains(req)");
153: return ((RequestCacheObject) (cache_.get(redir)))
154: .isAlive();
155: } else
156: // this is a non-cacheable request
157: return false;
158:
159: } else {
160:
161: // if the cache contains the sql request
162: if (cache_.containsKey(req)) {
163: // logger.debug("RequestCache:isInCache contains(req)");
164: return ((RequestCacheObject) (cache_.get(req)))
165: .isAlive();
166: } else {
167: // if the cache does not contain the sql request
168: // we are going to test all items in cache to test the pattern
169: for (Enumeration e = cache_.keys(); e.hasMoreElements();) {
170: RequestCacheObject uco = (RequestCacheObject) (cache_
171: .get(e.nextElement()));
172: if (uco.getPattern().matcher(req).matches()) {
173: // if it matches, return if the RequestCacheObject is
174: // alive
175: // logger.debug("RequestCache:isInCache
176: // contains(pattern)");
177: return uco.isAlive();
178: }
179: }
180: }
181: }
182:
183: return false;
184: }
185:
186: public synchronized void setResult(String req, Object rset) {
187:
188: // if the cache exists and the sql request (or pattern) is not null
189: if ((cache_ != null) && (req != null)) {
190: // first remove the RequestCacheObject to the cache
191: RequestCacheObject uco = (RequestCacheObject) (cache_
192: .remove(req));
193: uco.setResult(rset);
194: // second, add the new changed object
195: cache_.put(req, uco);
196: }
197: }
198:
199: public Object getResult(String req) {
200:
201: // if the cache exists and it contains the pattern or sql request
202: if (cache_ != null) {
203: // return the stored object
204: String link = (String) (requests_.get(req));
205: if (link == null) {
206: // logger.debug("RequestCache:getResult link is null");
207: String rsql = getSqlPattern(req);
208: RequestCacheObject uco = (RequestCacheObject) (cache_
209: .get(rsql));
210:
211: return uco;
212: }
213: RequestCacheObject uco = (RequestCacheObject) (cache_
214: .get(link));
215: if (uco == null) {
216: // logger.debug("RequestCache:getResult uco is null");
217: return null;
218: }
219: Object obj = uco.getResult();
220:
221: if (obj != null)
222: return obj;
223:
224: }
225: return null;
226: }
227:
228: public String getSqlPattern(String sql) {
229: // try to parse all the cache to determine if the sql statement matches
230: // the defined pattern
231: if (cache_ != null)
232: if (cache_.size() == 0)
233: return null;
234:
235: for (Enumeration e = cache_.keys(); e.hasMoreElements();) {
236: RequestCacheObject uco = (RequestCacheObject) (cache_.get(e
237: .nextElement()));
238:
239: // if it matches, we return it
240: if (uco.getPattern().matcher(sql).matches()) {
241: // logger.debug("RequestCache:getSqlPattern yes, it matches
242: // req=<"+sql+">");
243: return uco.getRequest();
244: }
245: }
246: return null;
247: }
248:
249: /**
250: * make the link between a application request (sql) and the pattern found
251: * in the key of the cache_ object
252: *
253: * @param pattern :
254: * may be "null" String
255: */
256: public void setLink(String sql, String pattern) {
257:
258: if (cache_ != null)
259: if (cache_.size() != 0)
260: if ((requests_ != null) && (sql != null)
261: && (pattern != null)) {
262: requests_.put(sql, pattern);
263: }
264: }
265:
266: public synchronized void reset() {
267: // we need to remove all elements in cache
268: for (Enumeration e = cache_.keys(); e.hasMoreElements();) {
269: RequestCacheObject uco = (RequestCacheObject) (cache_.get(e
270: .nextElement()));
271: uco.close();
272: uco = null;
273: }
274:
275: // and now, to create again all elements from the configuration file
276: cache_.clear();
277: cache_ = null;
278: cache_ = new Hashtable();
279: requests_.clear();
280: requests_ = null;
281: requests_ = new Hashtable();
282: readConfigurationFile();
283: }
284:
285: public String toString() {
286: StringBuffer sbuf = new StringBuffer();
287: sbuf.append("=== DUMP REQUESTS ===\n");
288: for (Enumeration e = requests_.keys(); e.hasMoreElements();) {
289: String s = (String) e.nextElement();
290: sbuf.append("key=<" + s + "> value=<"
291: + (String) requests_.get(s) + ">\n");
292: }
293: sbuf.append("=== DUMP CACHE ===\n");
294: for (Enumeration e = cache_.keys(); e.hasMoreElements();) {
295: String s = (String) e.nextElement();
296: RequestCacheObject uco = (RequestCacheObject) cache_.get(s);
297: sbuf.append("key(pattern)=<" + s
298: + "> value(RequestCacheObject)=<" + uco.toString()
299: + ">\n");
300: }
301: return sbuf.toString();
302: }
303: }
|