001: /* Copyright 2005 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.tools.checks;
007:
008: import java.util.Iterator;
009: import java.util.List;
010:
011: import javax.servlet.ServletContext;
012: import javax.servlet.ServletContextEvent;
013: import javax.servlet.ServletContextListener;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017:
018: /**
019: * This context listener executes SafeDelegatingCheckRunner, logs its results,
020: * and exposes its results in the ServletContext.
021: *
022: * The intent is that the ICheckRunner delegate of SafeDelegatingCheckRunner,
023: * configured in Spring, be configured to run useful runtime sanity checks that will
024: * help uPortal deployers to understand what went wrong in their deployments
025: * when dependencies are not present.
026: *
027: *
028: * The current implementation logs successes only via Commons Logging whereas
029: * it logs failures via Commons Logging and via the Servlet API's logging
030: * mechanism and to System.err. This overkill of logging is intended to give the
031: * primary intended audience --
032: * new uPortal deployers who may not yet be comfortable with configuring uPortal
033: * logging -- the maximum chance of encountering the output.
034: *
035: * The intent is that in a healthy happy production uPortal deployment, no
036: * checks will fail and so this overkill of logging won't be a problem.
037: *
038: * Subclassing this class: this class is designed to be subclassed to replace the
039: * implementation of the method that logs the results from the SafeDelegatingCheckRunner.
040: * In this way you can implement some other logging strategy.
041: *
042: * @version $Revision: 35833 $ $Date: 2005-05-19 18:51:40 -0700 (Thu, 19 May 2005) $
043: * @since uPortal 2.5
044: */
045: public class CheckingContextListener implements ServletContextListener {
046:
047: /**
048: * The name of the servlet context attribute which this listener will set at
049: * context initialization to contain the List of CheckAndResult instances representing
050: * the results of running the configured checks.
051: */
052: public static final String RESULTS_SC_KEY = "org.jasig.portal.tools.checks.CheckingContextListener.RESULTS";
053:
054: protected final Log log = LogFactory.getLog(getClass());
055:
056: public final void contextInitialized(ServletContextEvent sce) {
057: /*
058: * This method is final because the intended extension strategy for this
059: * class is to accept this default implementation of check execution but to
060: * override the logResults method to implement alternative logging or other
061: * handling of the results.
062: */
063:
064: ServletContext servletContext = sce.getServletContext();
065:
066: SafeDelegatingCheckRunner checkRunner = new SafeDelegatingCheckRunner();
067:
068: List results = checkRunner.doChecks();
069:
070: logResults(results, servletContext);
071:
072: // we've already logged the results of each individual check. Now we
073: // expose the results of these checks in the ServletContext so that
074: // views such as JSPs, channels can render them.
075:
076: servletContext.setAttribute(RESULTS_SC_KEY, results);
077:
078: }
079:
080: public void contextDestroyed(ServletContextEvent sce) {
081: // do nothing
082: }
083:
084: /**
085: * Log the results reported by the check runner.
086: *
087: * You can subclass this class and override this method to change the
088: * logging behavior. You can also, by overriding this method and throwing
089: * a RuntimeException, veto the loading of the context.
090: *
091: * The default implementation of this method is safe such that it will not throw.
092: * Since the rest of contextInitialized is also safe, the default implementation
093: * of this ContextListener is safe and will not, no matter how abjectly the
094: * checks fail, itself abort the context initialization.
095: *
096: * @param results List of CheckAndResult instances
097: * @param servletContext the context in which we're running
098: */
099: protected void logResults(List results,
100: ServletContext servletContext) {
101:
102: if (results == null) {
103: log.error("Cannot log null results.");
104: return;
105: }
106:
107: for (Iterator iter = results.iterator(); iter.hasNext();) {
108:
109: try {
110: CheckAndResult checkAndResult = (CheckAndResult) iter
111: .next();
112:
113: if (checkAndResult.isSuccess()) {
114: log.info("Check ["
115: + checkAndResult.getCheckDescription()
116: + "] succeeded with message ["
117: + checkAndResult.getResult().getMessage()
118: + "]");
119: } else {
120: // the following overkill of logging is intended to help deployers who
121: // might not know where to look find a record of what went wrong.
122:
123: String logMessage = "Check ["
124: + checkAndResult.getCheckDescription()
125: + "] failed with message ["
126: + checkAndResult.getResult().getMessage()
127: + "] and remediation advice ["
128: + checkAndResult.getResult()
129: .getRemediationAdvice() + "]";
130:
131: log.fatal(logMessage);
132: System.err.println(logMessage);
133: servletContext.log(logMessage);
134: }
135: } catch (Throwable t) {
136: // we cannot let a logging error break our context listener and thereby
137: // bring down our whole application context.
138:
139: log.error("Error in logging results of checks", t);
140: }
141:
142: }
143:
144: }
145:
146: }
|