KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > util > GenericThrottle


1 /*
2  * Copyright 2004 Sun Microsystems, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17
18 package org.apache.roller.util;
19
20 import java.util.HashMap JavaDoc;
21 import java.util.Map JavaDoc;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.roller.util.cache.Cache;
25 import org.apache.roller.util.cache.CacheManager;
26 import org.apache.roller.util.cache.ExpiringCacheEntry;
27
28
29 /**
30  * A tool used to provide throttling support.
31  *
32  * The basic idea is that if the # of hits from a client within a certain
33  * interval of time is greater than the threshold value then the client is
34  * considered to be abusive.
35  */

36 public class GenericThrottle {
37     
38     private static Log log = LogFactory.getLog(GenericThrottle.class);
39     
40     // threshold and interval to determine who is abusive
41
private int threshold = 1;
42     private int interval = 0;
43     
44     // a cache to maintain the data
45
Cache clientHistoryCache = null;
46     
47     
48     public GenericThrottle(int thresh, int inter, int maxEntries) {
49         
50         // threshold can't be negative, that would mean everyone is abusive
51
if(thresh > -1) {
52             this.threshold = thresh;
53         }
54         
55         // interval must be a positive value
56
if(inter > 0) {
57             this.interval = inter;
58         }
59         
60         // max entries must be a positive value
61
if(maxEntries < 0) {
62             maxEntries = 1;
63         }
64         
65         // cache props
66
Map JavaDoc cacheProps = new HashMap JavaDoc();
67         cacheProps.put("id", "throttle");
68         cacheProps.put("size", ""+maxEntries);
69         cacheProps.put("timeout", ""+this.interval);
70         
71         // get cache instance. handler is null cuz we don't want to register it
72
this.clientHistoryCache = CacheManager.constructCache(null, cacheProps);
73     }
74     
75     
76     /**
77      * Process a new hit from the client.
78      *
79      * Each call to this method increments the hit count for the client and
80      * then returns a boolean value indicating if the hit has pushed the client
81      * over the threshold.
82      *
83      * @retuns true if client is abusive, false otherwise
84      */

85     public boolean processHit(String JavaDoc clientId) {
86         
87         if(clientId == null) {
88             return false;
89         }
90         
91         // see if we have any info about this client yet
92
ClientInfo client = null;
93         ExpiringCacheEntry cacheEntry = (ExpiringCacheEntry) this.clientHistoryCache.get(clientId);
94         if(cacheEntry != null) {
95             log.debug("HIT "+clientId);
96             client = (ClientInfo) cacheEntry.getValue();
97             
98             // this means entry had expired
99
if(client == null) {
100                 log.debug("EXPIRED "+clientId);
101                 this.clientHistoryCache.remove(clientId);
102             }
103         }
104         
105         // if we already know this client then update their hit count and
106
// see if they have surpassed the threshold
107
if(client != null) {
108             client.hits++;
109             
110             log.debug("STATUS "+clientId+" - "+client.hits+" hits since "+client.start);
111             
112             // abusive client
113
if(client.hits > this.threshold) {
114                 return true;
115             }
116             
117         } else {
118             log.debug("NEW "+clientId);
119             
120             // first timer
121
ClientInfo newClient = new ClientInfo();
122             newClient.hits = 1;
123             newClient.id = clientId;
124             
125             ExpiringCacheEntry newEntry = new ExpiringCacheEntry(newClient, this.interval);
126             this.clientHistoryCache.put(clientId, newEntry);
127         }
128         
129         return false;
130     }
131     
132     
133     /**
134      * Check the current status of a client.
135      *
136      * A client is considered abusive if the number of hits from the client
137      * within the configured interval is greater than the set threshold.
138      *
139      * @returns true if client is abusive, false otherwise.
140      */

141     public boolean isAbusive(String JavaDoc clientId) {
142         
143         if(clientId == null) {
144             return false;
145         }
146         
147         // see if we have any info about this client
148
ClientInfo client = null;
149         ExpiringCacheEntry cacheEntry = (ExpiringCacheEntry) this.clientHistoryCache.get(clientId);
150         if(cacheEntry != null) {
151             log.debug("HIT "+clientId);
152             client = (ClientInfo) cacheEntry.getValue();
153             
154             // this means entry had expired
155
if(client == null) {
156                 log.debug("EXPIRED "+clientId);
157                 this.clientHistoryCache.remove(clientId);
158             }
159         }
160         
161         if(client != null) {
162             return (client.hits > this.threshold);
163         } else {
164             return false;
165         }
166     }
167     
168     
169     // just something to keep a few properties in
170
private class ClientInfo {
171         
172         public String JavaDoc id = null;
173         public int hits = 0;
174         public java.util.Date JavaDoc start = new java.util.Date JavaDoc();
175         
176     }
177     
178 }
179
Popular Tags