001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.services.controller;
066:
067: import com.jcorporate.expresso.core.cache.CacheEntry;
068: import com.jcorporate.expresso.core.cache.CacheException;
069: import com.jcorporate.expresso.core.cache.CacheManager;
070: import com.jcorporate.expresso.core.cache.CacheSystem;
071: import com.jcorporate.expresso.core.cache.Cacheable;
072: import com.jcorporate.expresso.core.controller.ControllerException;
073: import com.jcorporate.expresso.core.controller.ControllerRequest;
074: import com.jcorporate.expresso.core.controller.ControllerResponse;
075: import com.jcorporate.expresso.core.controller.DBController;
076: import com.jcorporate.expresso.core.controller.Input;
077: import com.jcorporate.expresso.core.controller.Output;
078: import com.jcorporate.expresso.core.controller.State;
079: import com.jcorporate.expresso.core.controller.Transition;
080: import com.jcorporate.expresso.core.db.DBConnectionPool;
081: import com.jcorporate.expresso.core.db.DBException;
082: import com.jcorporate.expresso.core.dbobj.ValidValue;
083: import com.jcorporate.expresso.core.misc.ConfigManager;
084:
085: import java.util.Enumeration;
086: import java.util.Iterator;
087: import java.util.List;
088: import java.util.Vector;
089:
090: /**
091: * This Controller allows control of the CacheManager. It allows any or all caches
092: * to be cleared, and permits the current status of the cache to be displayed. This
093: * controller is called when the cache requires and update triggered from a seperate VM.
094: *
095: * @author Michael Nash
096: * @version $Revision: 1.18 $ $Date: 2004/11/17 20:48:17 $
097: */
098: public class CacheControl extends DBController {
099:
100: /**
101: * Our constructor "declares" what states we handle
102: */
103: public CacheControl() {
104: super ();
105:
106: State prompt = new State("prompt", "Prompt for Command");
107: addState(prompt);
108: setInitialState("prompt");
109:
110: State clearCache = new State("clear", "Clear Cache");
111: clearCache.addRequiredParameter("dbContext");
112: clearCache.addRequiredParameter("cache");
113: clearCache.addRequiredParameter("key");
114: clearCache.addRequiredParameter("nonotify");
115: addState(clearCache);
116:
117: State display = new State("display",
118: "Display Cache Information");
119: display.addRequiredParameter("dbContext");
120: display.addRequiredParameter("cache");
121: display.addRequiredParameter("key");
122: addState(display);
123: this
124: .setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
125:
126: } /* CacheControl() */
127:
128: /**
129: * Adds all cacheable items under the given output o
130: *
131: * @param o The parent output
132: * @param db The data context
133: * @param cacheName The name of the cache to get the outputs for
134: * @param key The key for the cache or 'all' if you want to retrieve
135: * all elements in the cache
136: */
137: private void addAllItems(Output o, String db, String cacheName,
138: String key) throws CacheException {
139: long curTime = System.currentTimeMillis();
140: CacheSystem cs = CacheManager.getCacheSystem(db);
141: if (key.equalsIgnoreCase("all")) {
142: List v = cs.getItems(cacheName);
143:
144: if (v == null) {
145: return;
146: }
147:
148: Cacheable oneItem = null;
149:
150: for (Iterator ei = v.iterator(); ei.hasNext();) {
151: oneItem = (Cacheable) ei.next();
152: CacheEntry ce = cs.getCache(cacheName).getCacheEntry(
153: oneItem.getKey());
154: if (ce != null) {
155: String outputContent = "Item '" + oneItem.getKey();
156: long expires = ce.getExpires();
157: if (expires > 0) {
158: outputContent = outputContent
159: + " [Expiration: "
160: + (int) ((expires - curTime) / 60000)
161: + " minutes]";
162: }
163: o.addNested(new Output(outputContent));
164: }
165: }
166: } else {
167: Cacheable oneItem = cs.getItem(cacheName, key);
168:
169: if (oneItem != null) {
170: o.addNested(new Output("Item '" + oneItem.getKey()));
171: } else {
172: o.addNested(new Output("No such item with key '" + key
173: + "' in cache '" + cacheName
174: + "' in db/context '" + db + "'"));
175: }
176: }
177: } /* addAllItems(Output, String, String, String) */
178:
179: /**
180: * Clears the cache
181: *
182: * @param request The ControllerRequest Object
183: * @param response the ControllerResposne
184: */
185: private void runClearState(ControllerRequest request,
186: ControllerResponse response) throws ControllerException {
187: try {
188: DBConnectionPool.reInitialize();
189: } catch (DBException de) {
190: throw new ControllerException(de);
191: }
192: if (!request.getParameter("key").equalsIgnoreCase("all")) {
193: if (request.getParameter("dbContext").equalsIgnoreCase(
194: "all")) {
195: throw new ControllerException(
196: "You cannot clear a specific key in all databases");
197: }
198: if (request.getParameter("cache").equalsIgnoreCase("all")) {
199: throw new ControllerException(
200: "You cannot clear a specific key in all caches");
201: }
202: }
203:
204: Vector dbVector = new Vector();
205:
206: if (request.getParameter("dbContext").equalsIgnoreCase("all")) {
207: for (Enumeration edb = ConfigManager.getAllConfigKeys(); edb
208: .hasMoreElements();) {
209: dbVector.addElement((String) edb.nextElement());
210: }
211: } else {
212: dbVector.addElement(request.getParameter("dbContext"));
213: }
214: try {
215: String oneDBName = null;
216:
217: for (Enumeration ecl = dbVector.elements(); ecl
218: .hasMoreElements();) {
219: oneDBName = (String) ecl.nextElement();
220:
221: if (request.getParameter("cache").equalsIgnoreCase(
222: "all")) {
223: if (!request.getParameter("nonotify")
224: .equals("true")) {
225: CacheManager.clearNoNotify(oneDBName);
226: } else {
227: CacheManager.clear(oneDBName);
228: }
229: } else {
230: if (request.getParameter("key").equalsIgnoreCase(
231: "all")) {
232: if (!request.getParameter("nonotify").equals(
233: "true")) {
234: CacheManager.clearNoNotify(oneDBName);
235: } else {
236: CacheManager.clear(oneDBName, request
237: .getParameter("cache"));
238: }
239: } else {
240: Cacheable oneItem = CacheManager.getItem(
241: oneDBName, request
242: .getParameter("cache"), request
243: .getParameter("key"));
244:
245: if (oneItem != null) {
246: if (!request.getParameter("nonotify")
247: .equals("true")) {
248: CacheManager.removeItemNoNotify(
249: oneDBName, request
250: .getParameter("cache"),
251: oneItem);
252: } else {
253: CacheManager.removeItem(oneDBName,
254: request.getParameter("cache"),
255: oneItem);
256: }
257: }
258: }
259: }
260: } /* for each db/context */
261:
262: } catch (CacheException ce) {
263: throw new ControllerException("Unable to clear cache", ce);
264: }
265:
266: Transition prompt = new Transition("Start Again", getClass()
267: .getName());
268: prompt.setName("prompt");
269: prompt.addParam(STATE_PARAM_KEY, "prompt");
270: response.addTransition(prompt);
271: } /* clearState() */
272:
273: /**
274: * Show the current state of the cache
275: *
276: * @param response the ControllerResponse Object
277: * @param request The ControllerRequest object
278: */
279: private void runDisplayState(ControllerRequest request,
280: ControllerResponse response) throws ControllerException {
281: if (!request.getParameter("key").equalsIgnoreCase("all")) {
282: if (request.getParameter("dbContext").equalsIgnoreCase(
283: "all")) {
284: throw new ControllerException(
285: "You cannot display a specific key in all databases");
286: }
287: if (request.getParameter("cache").equalsIgnoreCase("all")) {
288: throw new ControllerException(
289: "You cannot display a specific key in all caches");
290: }
291: }
292:
293: Vector dbVector = new Vector();
294:
295: if (request.getParameter("dbContext").equalsIgnoreCase("all")) {
296: for (Enumeration edb = ConfigManager.getAllConfigKeys(); edb
297: .hasMoreElements();) {
298: dbVector.addElement((String) edb.nextElement());
299: }
300: } else {
301: dbVector.addElement(request.getParameter("dbContext"));
302: }
303: try {
304: String oneDBName = null;
305:
306: for (Enumeration ecl = dbVector.elements(); ecl
307: .hasMoreElements();) {
308: oneDBName = (String) ecl.nextElement();
309:
310: Output oneDB = new Output("Database/Context '"
311: + oneDBName + "'");
312: response.addOutput(oneDB);
313:
314: Output oneCache = null;
315: String cacheName = null;
316:
317: if (request.getParameter("cache").equalsIgnoreCase(
318: "all")) {
319: Iterator c = CacheManager
320: .getAllCacheNamesIterator(oneDBName);
321:
322: if (c != null) {
323: while (c.hasNext()) {
324: cacheName = (String) c.next();
325: oneCache = new Output("Cache '" + cacheName
326: + "'");
327: oneDB.addNested(oneCache);
328: addAllItems(oneCache, oneDBName, cacheName,
329: request.getParameter("key"));
330: }
331: }
332: } else {
333: cacheName = request.getParameter("cache");
334: oneCache = new Output("Cache '" + cacheName + "'");
335: oneDB.addNested(oneCache);
336: addAllItems(oneCache, oneDBName, cacheName, request
337: .getParameter("key"));
338: }
339: } /* for each db/context */
340:
341: } catch (CacheException ce) {
342: throw new ControllerException("Unable to clear cache", ce);
343: }
344:
345: Runtime r = Runtime.getRuntime();
346: double avail = r.totalMemory();
347: double free = r.freeMemory();
348: double pfree = ((free / avail) * 100.000);
349: response.addOutput(new Output("Memory avail:" + avail
350: + ", Free:" + free + ", %free " + pfree));
351:
352: Transition prompt = new Transition("Start Again", getClass()
353: .getName());
354: prompt.setName("prompt");
355: prompt.addParam(STATE_PARAM_KEY, "prompt");
356: response.addTransition(prompt);
357: } /* displayState() */
358:
359: /**
360: * Return the title of this Controller
361: *
362: * @return the title of this controller
363: */
364: public String getTitle() {
365: return ("Cache Control");
366: } /* getTitle() */
367:
368: /**
369: * Prompt for the command to perform
370: *
371: * @param response The ControllerResponse object
372: * @param request The ControllerRequest object
373: */
374: private void runPromptState(ControllerRequest request,
375: ControllerResponse response) throws ControllerException {
376: Input db = new Input();
377: db.setLabel("Database/Context (or 'all')");
378: db.setName("dbContext");
379: db.setDefaultValue("all");
380: response.addInput(db);
381:
382: Input cache = new Input();
383: cache.setLabel("Cache Name (or 'all')");
384: cache.setName("cache");
385: cache.setDefaultValue("all");
386: response.addInput(cache);
387:
388: Input key = new Input();
389: key.setLabel("Cache Item Key (or 'all')");
390: key.setName("key");
391: key.setDefaultValue("all");
392: response.addInput(key);
393:
394: Input noNotify = new Input();
395: noNotify.setLabel("Skip Notifications of remote Caches?");
396: noNotify.setName("nonotify");
397: noNotify.setDefaultValue("true");
398: Vector vv = new Vector(2);
399: vv.add(new ValidValue("true", "true"));
400: vv.add(new ValidValue("false", "false"));
401: noNotify.setValidValues(vv);
402: response.addInput(noNotify);
403:
404: Transition clear = new Transition("Clear Cache", getClass()
405: .getName());
406: clear.setName("clear");
407: clear.addParam(STATE_PARAM_KEY, "clear");
408: response.addTransition(clear);
409:
410: Transition display = new Transition("Display Cache", getClass()
411: .getName());
412: display.setName("display");
413: display.addParam(STATE_PARAM_KEY, "display");
414: response.addTransition(display);
415: } /* promptState() */
416:
417: } /* CacheControl */
|