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.CacheManager;
068: import com.jcorporate.expresso.core.controller.Block;
069: import com.jcorporate.expresso.core.controller.ControllerException;
070: import com.jcorporate.expresso.core.controller.ControllerRequest;
071: import com.jcorporate.expresso.core.controller.ControllerResponse;
072: import com.jcorporate.expresso.core.controller.DBController;
073: import com.jcorporate.expresso.core.controller.NonHandleableException;
074: import com.jcorporate.expresso.core.controller.Output;
075: import com.jcorporate.expresso.core.controller.ServletControllerRequest;
076: import com.jcorporate.expresso.core.controller.State;
077: import com.jcorporate.expresso.core.controller.Transition;
078: import com.jcorporate.expresso.core.db.DBConnection;
079: import com.jcorporate.expresso.core.db.DBConnectionPool;
080: import com.jcorporate.expresso.core.db.DBException;
081: import com.jcorporate.expresso.core.db.TypeMapper;
082: import com.jcorporate.expresso.core.dbobj.CacheStatEntry;
083: import com.jcorporate.expresso.core.dbobj.DBObject;
084: import com.jcorporate.expresso.core.misc.ConfigManager;
085: import com.jcorporate.expresso.core.misc.ConfigurationException;
086: import com.jcorporate.expresso.core.misc.CurrentLogin;
087: import com.jcorporate.expresso.core.misc.DateTime;
088: import com.jcorporate.expresso.core.misc.StringUtil;
089: import com.jcorporate.expresso.core.security.User;
090: import com.jcorporate.expresso.services.dbobj.DBObjLimit;
091: import com.jcorporate.expresso.services.dbobj.GroupMembers;
092: import com.jcorporate.expresso.services.dbobj.Setup;
093:
094: import javax.servlet.ServletException;
095: import javax.servlet.http.Cookie;
096: import javax.servlet.http.HttpServletRequest;
097: import java.text.NumberFormat;
098: import java.text.SimpleDateFormat;
099: import java.util.ArrayList;
100: import java.util.Calendar;
101: import java.util.Collections;
102: import java.util.Date;
103: import java.util.Enumeration;
104: import java.util.Hashtable;
105: import java.util.Iterator;
106: import java.util.Locale;
107: import java.util.Map;
108: import java.util.TreeMap;
109:
110: /**
111: * Status servlet shows some current information about the servlet
112: * system and it's database connections and server-side tasks
113: *
114: * @author Michael Nash
115: * @since Expresso 2 as a servlet Expresso 4 as a controller
116: */
117: public class Status extends DBController {
118:
119: /**
120: * Our constructor "declares" what states we handle
121: */
122: public Status() {
123: super ();
124:
125: State show = new State("show", "Show Status");
126: show.addOptionalParameter("contextName");
127: addState(show);
128: setInitialState("show");
129:
130: State packages = new State("showPackages",
131: "Show Installed Packages");
132: addState(packages);
133: this
134: .setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
135: } /* Status() */
136:
137: /**
138: * Shows the currently installed packages on the system
139: *
140: * @param request The controllerRequest object
141: * @param response The controllerResponse object
142: * @throws ControllerException upon Error
143: * @throws NonHandleableException upon Fatal Error
144: */
145: protected void runShowPackagesState(ControllerRequest request,
146: ControllerResponse response) throws ControllerException,
147: NonHandleableException {
148:
149: showPackages(request, response);
150: showTransitions(request, response);
151: }
152:
153: /**
154: * Display the status information
155: *
156: * @param request Standard request object
157: * @param response Standard response object
158: * @throws ControllerException If an uncaught exception occurs
159: * @throws NonHandleableException upon fatal error
160: */
161: protected void runShowState(ControllerRequest request,
162: ControllerResponse response) throws ControllerException,
163: NonHandleableException {
164: String displayContext = request.getParameter("contextName");
165: if (displayContext == null || displayContext.length() == 0) {
166: displayContext = "default";
167: }
168:
169: /* The code below has been modified to comply with the new
170:
171: named connection release. */
172: try {
173: String userName = request.getUser();
174: Output t = null;
175:
176: if (userName == null) {
177: t = new Output(
178: "general",
179: response.getString("Status_at")
180: + DateTime.getDateTimeString()
181: + response
182: .getString("_Not_logged_in._Logging_level_is_")
183: + Setup.getValue(request
184: .getDataContext(), "LogLevel"));
185: } else {
186: Locale l = request.getLocale();
187: String language = l.getLanguage();
188: String country = l.getCountry();
189: String dbDescrip = "";
190:
191: try {
192: dbDescrip = StringUtil.notNull(ConfigManager
193: .getContext(request.getDataContext())
194: .getDescription());
195: } catch (ConfigurationException ce) {
196: throw new ControllerException(ce);
197: }
198: if (dbDescrip.equals("")) {
199: dbDescrip = request.getDataContext();
200: }
201:
202: Object[] args = { userName, dbDescrip,
203: language + "/" + country };
204: t = new Output("general", response
205: .getString("Status_at")
206: + DateTime.getDateTimeString()
207: + response.getString("Logged_in_as", args));
208: }
209:
210: response.add(t);
211:
212: Block oneRow = null;
213:
214: /* Now show the connection info from the connection pool */
215: showContextInformation(request, response, displayContext);
216:
217: /* Now show any cookies the client has */
218: Block cookieTable = new Block("cookies");
219: cookieTable.setAttribute("table", "Y");
220: cookieTable.setDescription(response.getString("Cookies"));
221: cookieTable.setAttribute("header-row", response
222: .getString("Name|Value"));
223:
224: /* Normally, accessing the HttpServletRequest/Response objects is a very bad
225:
226: * idea. The fact that this controller does it means that it is non-portable
227:
228: * outside the servlet environment
229:
230: */
231: ServletControllerRequest sr = (ServletControllerRequest) request;
232: HttpServletRequest hreq = (HttpServletRequest) sr
233: .getServletRequest();
234: Cookie[] cookies = hreq.getCookies();
235: String name = null;
236: String value = null;
237:
238: if (cookies != null) {
239: for (int i = 0; i < cookies.length; i++) {
240: oneRow = new Block();
241: oneRow.setAttribute("row", "Y");
242: name = StringUtil.notNull(cookies[i].getName());
243: value = StringUtil.notNull(cookies[i].getValue());
244: oneRow.add(new Output(name));
245: oneRow.add(new Output(value));
246: cookieTable.add(oneRow);
247: } /* for each cookie */
248:
249: } /* if cookies were not null */
250:
251: response.add(cookieTable);
252: response.add(new Output("memory1", response
253: .getString("Total_Memory_")
254: + Runtime.getRuntime().totalMemory()));
255: response.add(new Output("memory2", response
256: .getString("Free_Memory_")
257: + Runtime.getRuntime().freeMemory()));
258: CacheManager.displayStatus();
259:
260: /* Now show mappings to other databases (databases other
261: than default. */
262: Hashtable dbMapHash = ConfigManager.getOtherDBLocations();
263:
264: if (dbMapHash == null) {
265: response
266: .add(new Output(
267: "No mappings to databases other "
268: + "than the default database could be found. The DBOtherMap is empty."));
269: } else {
270: Block mapTable = new Block("dbother");
271: mapTable.setDescription("Mappings to Other Databases");
272: mapTable.setAttribute("table", "Y");
273: mapTable.setAttribute("header-row",
274: "Context|DBObject Class Name|Database Mapping");
275:
276: if (dbMapHash.size() == 0) {
277: response
278: .add(new Output("No entries in DBOtherMap"));
279: } else {
280: response.add(mapTable);
281: }
282:
283: String objectName = null;
284: String dbMapping = null;
285:
286: for (Enumeration emap = dbMapHash.keys(); emap
287: .hasMoreElements();) {
288: objectName = (String) emap.nextElement();
289: java.util.StringTokenizer st = new java.util.StringTokenizer(
290: objectName, "|");
291: String contextName = st.nextToken();
292: String dbObjName = st.nextToken();
293: dbMapping = (String) dbMapHash.get(objectName);
294:
295: Block aRow = new Block("new row");
296: aRow.setAttribute("row", "Y");
297: aRow.add(new Output(contextName));
298: aRow.add(new Output(dbObjName));
299: aRow.add(new Output(dbMapping));
300: mapTable.add(aRow);
301: }
302: } // End of mappings to other Databases table.
303:
304: /* Now see if we can get caching status from db object */
305: Map cacheStats = DBObject.getCacheStatsMap();
306:
307: if (cacheStats == null) {
308: response
309: .add(new Output(
310: "Caching statistics not "
311: + "currently available. Edit expresso-config.xml "
312: + "to begin collecting cache statistics"));
313: } else {
314: Block statsTable = new Block("dbstats");
315: statsTable.setDescription("DB Object Statistics");
316: statsTable.setAttribute("table", "Y");
317: statsTable
318: .setAttribute(
319: "header-row",
320: "Object (adjust cache)|Hit %|Reads|Cache Hits|Cache Misses|Cache Size|DB/Context");
321:
322: if (cacheStats.size() == 0) {
323: response
324: .add(new Output("No entries in cache stats"));
325: } else {
326: response.add(statsTable);
327: }
328:
329: double hits = 0;
330: double misses = 0;
331: double reads = 0;
332: double perc = 0.0;
333:
334: NumberFormat numFormat = NumberFormat.getInstance();
335: numFormat.setMaximumFractionDigits(0);
336: numFormat.setGroupingUsed(true);
337: NumberFormat percentFormat = NumberFormat
338: .getPercentInstance();
339: percentFormat.setMaximumFractionDigits(1);
340:
341: ArrayList list = new ArrayList(cacheStats.values());
342: Collections.sort(list); // entries sort by hit rate
343: for (Iterator ee = list.iterator(); ee.hasNext();) {
344: CacheStatEntry oneEntry = (CacheStatEntry) ee
345: .next();
346: if (oneEntry.getDataContext().equalsIgnoreCase(
347: displayContext)) {
348: reads = oneEntry.getReadCount();
349: hits = oneEntry.getCacheHits();
350: misses = oneEntry.getCacheMisses();
351: perc = (hits / reads);
352:
353: Block aRow = new Block("new row");
354: aRow.setAttribute("row", "Y");
355: // aRow.add(new Output(oneEntry.getDBObjName()));
356: Transition trans = new Transition(oneEntry
357: .getDBObjName(), DBMaint.class,
358: DBMaint.UPDATE);
359: trans.addParam("key", oneEntry.getDBObjName());
360: trans.addParam("dbobj", DBObjLimit.class
361: .getName());
362: aRow.add(trans);
363:
364: aRow.add(new Output(""
365: + percentFormat.format(perc)));
366: aRow.add(new Output(""
367: + numFormat.format(reads)));
368: aRow
369: .add(new Output(""
370: + numFormat.format(hits)));
371: aRow.add(new Output(""
372: + numFormat.format(misses)));
373:
374: DBObject oneObj = null;
375: try {
376: Class c = Class.forName(oneEntry
377: .getDBObjName());
378: oneObj = (DBObject) c.newInstance();
379: } catch (ClassNotFoundException cn) {
380: throw new ServletException(
381: "Database object '"
382: + oneEntry.getDBObjName()
383: + "' not found", cn);
384: } catch (InstantiationException ie) {
385: throw new ServletException(
386: "Database object '"
387: + oneEntry.getDBObjName()
388: + "' cannot be instantiated",
389: ie);
390: } catch (IllegalAccessException iae) {
391: throw new ServletException(
392: "llegal access loading "
393: + "Database object '"
394: + oneEntry.getDBObjName()
395: + "'", iae);
396: }
397:
398: oneObj
399: .setDataContext(oneEntry
400: .getDataContext());
401: aRow
402: .add(new Output(""
403: + oneObj.getCacheSize()));
404:
405: aRow.add(new Output(oneEntry.getDataContext()));
406: statsTable.add(aRow);
407: }
408: }
409: }
410:
411: Hashtable allSessions = ConfigManager.getCurrentLogins();
412: response.add(new Output("Currently there are "
413: + allSessions.size() + " users connected"));
414:
415: if (userName.equalsIgnoreCase(User.ADMIN_USER)) {
416: Block userTable = new Block("User_Table");
417: userTable.setAttribute("table", "Y");
418: userTable
419: .setAttribute("header-row",
420: "User|Session|IP Address|Logged In At|DB/Context");
421: userTable.setDescription("Logged In Users");
422:
423: CurrentLogin oneLogin = null;
424: String oneSessionId = null;
425:
426: for (Enumeration cu = allSessions.keys(); cu
427: .hasMoreElements();) {
428: oneSessionId = (String) cu.nextElement();
429: oneLogin = (CurrentLogin) allSessions
430: .get(oneSessionId);
431:
432: if (oneLogin != null) {
433: oneRow = new Block();
434: oneRow.setAttribute("row", "Y");
435: if (oneLogin.getDBName().equalsIgnoreCase(
436: displayContext)) {
437: oneRow.add(new Output(oneLogin
438: .getUserName()));
439: oneRow.add(new Output(oneSessionId));
440: oneRow.add(new Output(oneLogin
441: .getIPAddress()));
442: oneRow.add(new Output(new Date(oneLogin
443: .getLogInTime()).toString()));
444: oneRow
445: .add(new Output(oneLogin
446: .getDBName()));
447: userTable.add(oneRow);
448: }
449: }
450: }
451:
452: response.add(userTable);
453: showTransitions(request, response);
454: }
455:
456: } catch (Exception he) {
457: throw new ControllerException(he);
458: }
459: } /* doGet(HttpServletRequest, HttpServletResponse) */
460:
461: /**
462: * Fill out the context information as s
463: *
464: * @param request The ControllerRequest object
465: * @param response The ControllerResponse Object
466: * @param contextName The data context to show the data for
467: * @throws ControllerException upon error
468: * @throws DBException upon data access error
469: */
470: protected void showContextInformation(ControllerRequest request,
471: ControllerResponse response, String contextName)
472: throws ControllerException, DBException {
473: /* One nested block in this block for each connection pool */
474: Block oneRow = null;
475: Block poolBlock = new Block("pools");
476: response.add(poolBlock);
477: String userName = request.getUser();
478:
479: String dbDescrip = "";
480:
481: try {
482: dbDescrip = StringUtil.notNull(ConfigManager.getContext(
483: contextName).getDescription());
484: } catch (ConfigurationException ce) {
485: throw new ControllerException(ce);
486: }
487: if (dbDescrip.equals("")) {
488: dbDescrip = contextName;
489: }
490:
491: Block this PoolBlock = new Block("Block for connection pool "
492: + contextName);
493: this PoolBlock.setDescription(dbDescrip);
494: poolBlock.add(this PoolBlock);
495:
496: //Object[] args = { oneConfigKey };
497: //response.add(new Output(getString("Connection_Pool_DB", args)));
498: Block oneTable = new Block("connection pool table "
499: + contextName + " database");
500: oneTable.setDescription("Connections for " + dbDescrip);
501: oneTable.setAttribute("table", "Y");
502:
503: if (userName == null) {
504: userName = ("");
505: }
506: if (userName.equalsIgnoreCase(User.ADMIN_USER)) {
507: oneTable
508: .setAttribute(
509: "header-row",
510: response
511: .getString("Connection_Number|Description|Status|Last_Touched|Last_SQL"));
512: } else {
513: oneTable
514: .setAttribute(
515: "header-row",
516: response
517: .getString("Connection_Number|Description|Status|Last_Touched"));
518: }
519:
520: DBConnectionPool currPool = DBConnectionPool
521: .getInstance(contextName);
522: DBConnection oneConnection = null;
523: int connectionNumber = 0;
524: Calendar c = Calendar.getInstance();
525: SimpleDateFormat df = new SimpleDateFormat(
526: "E',' MMM d yyyy 'at' hh:mm:ss a");
527:
528: for (Iterator e = currPool.getPoolList().iterator(); e
529: .hasNext();) {
530: connectionNumber++;
531: oneConnection = (DBConnection) e.next();
532: oneRow = new Block();
533: oneRow.setAttribute("row", "Y");
534: oneRow.add(new Output("" + connectionNumber));
535: oneRow.add(new Output(oneConnection.getDescription()));
536:
537: if (oneConnection.isAvailable()) {
538: oneRow.add(new Output("AVAILABLE"));
539: } else {
540: oneRow.add(new Output("IN USE"));
541: }
542: long l = oneConnection.getLastTouched();
543: c.setTime(new Date(l));
544:
545: df.setCalendar(c);
546: oneRow.add(new Output(df.format(c.getTime())));
547:
548: if (userName.equalsIgnoreCase(User.ADMIN_USER)) {
549: oneRow.add(new Output(oneConnection.getSQL()));
550: }
551:
552: oneTable.add(oneRow);
553: } /* for each connection in the default pool */
554:
555: if (oneTable.getNumContents() > 0) {
556: this PoolBlock.add(oneTable);
557: }
558:
559: GroupMembers oneGroupMembers = new GroupMembers();
560: oneGroupMembers.setDataContext(request.getDataContext());
561: TypeMapper typeMapper = TypeMapper.getInstance(contextName);
562:
563: Map expressoToSQLTypes = typeMapper.getExpressoToSQLMap();
564:
565: // Hashtable expressoToSQLTypes = Schema.getExpressoToSQLMap(
566: // request.getDBName());
567: // Hashtable SQLtoDBMap = Schema.getSQLToDBMap(
568: // request.getDBName());
569:
570: /* Now display the type map */
571: Block typeMapTable = new Block("Type_Map_Table" + contextName);
572: typeMapTable.setDescription("Type Mappings for " + dbDescrip);
573: typeMapTable.setAttribute("table", "Y");
574: typeMapTable.setAttribute("header-row", response
575: .getString("mapHeader"));
576:
577: String oneDatabaseTypeName = null;
578: String oneJavaSQLTypeName = null;
579: String oneExpressoTypeName = null;
580:
581: for (Iterator en = expressoToSQLTypes.keySet().iterator(); en
582: .hasNext();) {
583: oneExpressoTypeName = (String) en.next();
584:
585: // oneDBTypeName = (String) SQLtoDBMap.get(oneSQLTypeName);
586: // if (oneDBTypeName == null) {
587: // oneDBTypeName = "Not Mapped";
588: // }
589: // oneExpressoTypeName = oneJavaSQLTypeName;
590: Integer sqlType = typeMapper
591: .getExpressoToJava(oneExpressoTypeName
592: .toLowerCase());
593: if (sqlType == null) {
594: oneJavaSQLTypeName = "Not Mapped";
595: oneDatabaseTypeName = "Not Mapped";
596: } else {
597: oneJavaSQLTypeName = typeMapper.getNameForSQL(sqlType
598: .intValue());
599: if (oneJavaSQLTypeName == null) {
600: oneJavaSQLTypeName = "No Name (" + sqlType + ")";
601: }
602:
603: Map sqlToDB = typeMapper.getSQLToDBMap();
604:
605: oneDatabaseTypeName = (String) sqlToDB.get(sqlType);
606:
607: if (oneDatabaseTypeName == null) {
608: oneDatabaseTypeName = "Not Mapped";
609: }
610:
611: }
612:
613: oneRow = new Block();
614: oneRow.setAttribute("row", "Y");
615: oneRow.add(new Output(oneExpressoTypeName));
616: oneRow.add(new Output(oneJavaSQLTypeName));
617: oneRow.add(new Output(oneDatabaseTypeName));
618: typeMapTable.add(oneRow);
619: }
620:
621: this PoolBlock.add(typeMapTable);
622:
623: }
624:
625: /**
626: * Adds the transitions to switch between 'show' states
627: *
628: * @param request The controllerRequest object
629: * @param response the ControllerResponse object
630: * @throws ControllerException upon error
631: */
632: protected void showTransitions(ControllerRequest request,
633: ControllerResponse response) throws ControllerException {
634: String currentState = StringUtil.notNull(request
635: .getParameter(STATE_PARAM_KEY));
636: if (currentState.length() == 0) {
637: currentState = "show";
638: }
639: boolean showState = (currentState.equals("show"));
640: String currentContextName = request.getParameter("contextName");
641: if (currentContextName == null
642: || currentContextName.length() == 0) {
643: currentContextName = "default";
644: }
645:
646: for (Enumeration e = ConfigManager.getAllConfigKeys(); e
647: .hasMoreElements();) {
648: String oneKey = (String) e.nextElement();
649: Transition t = new Transition("show" + oneKey, "Show '"
650: + oneKey + "' Context Status", this .getClass(),
651: "show");
652: t.addParam("contextName", oneKey);
653: if (showState) {
654: if (currentContextName.equals(oneKey)) {
655: t.setAttribute("current", "y");
656: }
657: }
658: response.add(t);
659: }
660:
661: Transition t = new Transition("showPackages", this );
662: t.setLabel("Show Installed Packages");
663: if (!showState) {
664: t.setAttribute("current", "y");
665: }
666: response.add(t);
667: }
668:
669: /**
670: * Show all the packages that are installed
671: *
672: * @param request the ControllerRequest object
673: * @param response the ControllerResponse object
674: * @throws ControllerException upon error
675: */
676: protected void showPackages(ControllerRequest request,
677: ControllerResponse response) throws ControllerException {
678: Map sortedMap = new TreeMap();
679: Block packageBlock = new Block("packages");
680: response.add(packageBlock);
681: packageBlock.add(new Output("Currently installed packages"));
682: Block packageTable = new Block("packageTable");
683: packageTable.setAttribute("table", "Y");
684: packageTable
685: .setAttribute(
686: "header-row",
687: "Name|Impl. Title|Impl. Vendor|"
688: + "Impl. Version|Spec. Title|Spec. Vendor|Spec. Version|Is Sealed ");
689: packageBlock.add(packageTable);
690:
691: Package packages[] = Package.getPackages();
692: if (packages == null) {
693: return;
694: }
695:
696: for (int i = 0; i < packages.length; i++) {
697: sortedMap.put(packages[i].getName(), packages[i]);
698: }
699:
700: for (Iterator i = sortedMap.keySet().iterator(); i.hasNext();) {
701: String packageKey = (String) i.next();
702: Package onePackage = (Package) sortedMap.get(packageKey);
703: Block oneRow = new Block();
704: packageTable.add(oneRow);
705: oneRow.setAttribute("row", "Y");
706:
707: oneRow.add(new Output(StringUtil.notNull(onePackage
708: .getName())));
709: oneRow.add(new Output(StringUtil.notNull(onePackage
710: .getImplementationTitle())));
711: oneRow.add(new Output(StringUtil.notNull(onePackage
712: .getImplementationVendor())));
713: oneRow.add(new Output(StringUtil.notNull(onePackage
714: .getImplementationVersion())));
715: oneRow.add(new Output(StringUtil.notNull(onePackage
716: .getSpecificationTitle())));
717: oneRow.add(new Output(StringUtil.notNull(onePackage
718: .getSpecificationVendor())));
719: oneRow.add(new Output(StringUtil.notNull(onePackage
720: .getSpecificationVersion())));
721: if (onePackage.isSealed()) {
722: oneRow.add(new Output("YES"));
723: } else {
724: oneRow.add(new Output("no"));
725: }
726:
727: }
728:
729: }
730:
731: /**
732: * @return java.lang.String The Title of the controller
733: */
734: public String getTitle() {
735: return ("System Status");
736: }
737: } /* Status */
|