/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.jini.tool.envcheck;
import java.util.HashSet;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
/**
* A class which provides a standard way to report the results of
* a test.
*/
public abstract class Reporter {
/** the level at which information messages are generated */
public final static int INFO = 0;
/** the level at which warning messages are generated */
public final static int WARNING = 1;
/** the level at which error messages are generated */
public final static int ERROR = 2;
/** the header label for the source record */
private static String sourceString;
/** the header labels for the test result records */
private static String[] msgHeaders = new String[3];
/** flag controlling display of explanation text */
private static boolean explain = false;
/** the display reportingLevel */
private static int reportingLevel = WARNING;
/** the warning count */
private static int warningCount = 0;
/** the error count */
private static int errorCount = 0;
/** flag controlling printing stack traces */
private static boolean traces = false;
/** table of explanations which have been output, to inhibit duplicates */
private static HashSet explanationsGiven = new HashSet();
/** initialize the localized header labels */
static {
ResourceBundle bundle = Util.getResourceBundle(EnvCheck.class);
msgHeaders[0] = Util.getString("reporter.info", bundle);
msgHeaders[1] = Util.getString("reporter.warning", bundle);
msgHeaders[2] = Util.getString("reporter.error", bundle);
sourceString = Util.getString("reporter.source", bundle);
}
// inhibit instantiation
private Reporter(){
}
/**
* Set the reporting level. No validity checks are done.
*
* @param level the max level to generate output
*/
public static void setLevel(int level) {
reportingLevel = level;
}
/**
* Set the explanation generation flag;
*
* @param explain the value to set the flag to
*/
public static void setExplanation(boolean explain) {
Reporter.explain = explain;
}
/**
* Set the flag controlling printing of stack traces.
*
* @param traces if <code>true</code>, print stack traces
*/
public static void setPrintTraces(boolean traces) {
Reporter.traces = traces;
}
/**
* Generate the output for <code>message</code> . This method is silent
* if the message level is less than <code>reportLevel</code>.
* If <code>explain</code> is <code>true</code>, the explanation text
* will be output only the first time it is encountered.
*
* @param message the <code>Message</code> to print
*/
public static void print(Message message) {
print(message, null);
}
/**
* Generate the output for <code>message.</code> This method is silent if
* the message level is less than <code>Reporter.level</code>. If
* <code>Reporter.explain</code> is <code>true</code>, the explanation text
* will be output only the first time it is encountered. If
* <code>source</code> is <code>null</code>, the source record is not
* output. If the message level is error or warning, the appropriate counter
* is updated.
*
* @param message the <code>Message</code> to print
* @param source additional information identifying the component under test
*/
public static void print(Message message, String source) {
int messageLevel = message.getLevel();
if (reportingLevel > messageLevel) {
return;
}
if (messageLevel == WARNING) {
warningCount++;
} else if (messageLevel == ERROR) {
errorCount++;
}
System.out.println();
System.out.println(msgHeaders[messageLevel]
+ " "
+ message.getMessage());
if (source != null) {
System.out.println(sourceString + " " + source);
}
if (explain) {
printExplanation(message);
}
if (traces) {
message.printStackTrace(); // noop if no exception
}
}
/**
* Output the explanation text supplied by <code>message.</code> If there is
* no explanation text, or if the text has been output previously, this
* method returns. Otherwise the text is output. Formatting is applied if
* <code>message.formatExplanation()</code> returns <code>true</code>.
*
* @param message the <code>Message</code> to explain
*/
private static void printExplanation(Message message) {
String exp = message.getExplanation();
if (exp == null) {
return;
}
if (explanationsGiven.contains(exp)) {
return;
}
explanationsGiven.add(exp);
if (message.formatExplanation()) {
String indent = " ";
int lineMax = 70;
StringBuffer buf = new StringBuffer();
StringTokenizer tok = new StringTokenizer(exp);
int lineStart = 0;
while (tok.hasMoreTokens()) {
String nextWord = tok.nextToken();
int lineLength =
buf.length() + nextWord.length() + 1 - lineStart;
if (lineLength > lineMax) {
buf.append("\n");
lineStart = buf.length();
}
if (lineStart == buf.length()) {
buf.append(indent);
} else {
buf.append(" ");
}
buf.append(nextWord);
}
if (buf.length() > lineStart) {
buf.append("\n");
}
exp = buf.toString();
if (exp.length() > 0) {
System.out.println();
}
}
System.out.println(exp);
}
/**
* Get the total number of warning records that were generated.
*
* @return the warning count
*/
public static int getWarningCount() {
return warningCount;
}
/**
* Get the total number of error records that were generated.
*
* @return the error count
*/
public static int getErrorCount() {
return errorCount;
}
/**
* A container of message information to be processed by
* <code>Reporter</code>.
*/
public static class Message {
/** optional exception associated with the message */
private Throwable thrownException = null;
/** the brief message text */
private String message = null;
/** the full explanation text */
private String explanation = null;
/** the message level, initialized to an illegal value */
private int level = -1;
/** flag to format the explanation */
private boolean formatExplanation = true;
/**
* Construct a <code>Message</code> having the given level
* and text.
*
* @param level the message level
* @param message the short message text
* @param explanation the explanation text
*/
public Message(int level, String message, String explanation) {
this.level = level;
this.message = message;
this.explanation = explanation;
}
/**
* Construct a <code>Message</code> having the given level,
* text, and exception data.
*
* @param level the message level
* @param message the short message text
* @param thrownException the exception associated with the message
* @param explanation the explanation text
*/
public Message(int level,
String message,
Throwable thrownException,
String explanation)
{
this.level = level;
this.message = message;
this.thrownException = thrownException;
this.explanation = explanation;
}
/**
* Returns the message level.
*
* @return the level
*/
protected int getLevel() {
if (level == -1) {
throw new IllegalStateException("Bad Level");
}
return level;
}
/**
* Returns the short message text. If a non-<code>null</code> exception
* is associated with this message, the exception message is
* appended to the short message.
*
* @return the short message
*/
protected String getMessage() {
String buf = "";
if (message != null) {
buf = message;
if (thrownException != null) {
buf += ": ";
}
}
if (thrownException != null) {
buf += thrownException.getMessage();
}
if (buf.length() == 0) {
throw new IllegalStateException("No Message");
}
return buf;
}
/**
* Returns the explanation text.
*
* @return the explanation text
*/
protected String getExplanation() {
return explanation;
}
/**
* Prints a stack trace for the exception associated with this
* message. If there is no such exception this method returns silently.
*/
protected void printStackTrace() {
if (thrownException != null) {
thrownException.printStackTrace();
}
}
/**
* Set the flag indicating whether to format the explanation text.
*
* @param b if <code>true</code>, format the text
*/
protected void setFormatExplanation(boolean b) {
formatExplanation = b;
}
/**
* Returns the flag indicating whether to format the explanation text.
*
* @return <code>true</code> if the text is to be formatted.
*/
protected boolean formatExplanation() {
return formatExplanation;
}
}
}