blob: 147c35f64ad121533724f26f1f840efc692b871a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Oracle Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Gerry Kessler/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.validation.internal;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jst.jsf.common.dom.TagIdentifier;
import org.eclipse.jst.jsf.common.internal.JSPUtil;
import org.eclipse.jst.jsf.common.internal.types.CompositeType;
import org.eclipse.jst.jsf.common.internal.types.TypeComparator;
import org.eclipse.jst.jsf.common.metadata.Entity;
import org.eclipse.jst.jsf.common.metadata.Trait;
import org.eclipse.jst.jsf.common.metadata.query.ITaglibDomainMetaDataModelContext;
import org.eclipse.jst.jsf.common.metadata.query.TaglibDomainMetaDataQueryHelper;
import org.eclipse.jst.jsf.common.sets.AxiomaticSet;
import org.eclipse.jst.jsf.common.sets.ConcreteAxiomaticSet;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IDOMContextResolver;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.resolver.structureddocument.ITaglibContextResolver;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.internal.tld.TagIdentifierFactory;
import org.eclipse.jst.jsf.core.set.constraint.MemberConstraint;
import org.eclipse.jst.jsf.core.set.mapping.ElementToTagIdentifierMapping;
import org.eclipse.jst.jsf.core.tagmatcher.EvaluationException;
import org.eclipse.jst.jsf.core.tagmatcher.InvalidExpressionException;
import org.eclipse.jst.jsf.core.tagmatcher.XPathMatchingAlgorithm;
import org.eclipse.jst.jsf.metadataprocessors.MetaDataEnabledProcessingFactory;
import org.eclipse.jst.jsf.metadataprocessors.features.ELIsNotValidException;
import org.eclipse.jst.jsf.metadataprocessors.features.IValidELValues;
import org.eclipse.jst.jsf.metadataprocessors.features.IValidValues;
import org.eclipse.jst.jsf.metadataprocessors.features.IValidationMessage;
import org.eclipse.jst.jsf.validation.internal.constraints.ContainsTagConstraint;
import org.eclipse.jst.jsf.validation.internal.constraints.TagId;
import org.eclipse.jst.jsf.validation.internal.constraints.TagSet;
import org.eclipse.jst.jsf.validation.internal.el.ELExpressionValidator;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.ValidationMessageFactory;
import org.eclipse.jst.jsp.core.internal.domdocument.DOMModelForJSP;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.internal.validation.JSPValidator;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* A JSP page validator that makes use of the JSF metadata processing framework so that JSP page
* semantics can be validated.
*
* This implementation currently only validates attribute values.
* @author Gerry Kessler - Oracle
*/
public class JSPSemanticsValidator extends JSPValidator implements ISourceValidator
{
// TODO: should the source validator be a separate class in jsp.ui?
// problem with simple split off is that preference must also be split off
static final boolean DEBUG;
static {
String value = Platform.getDebugOption("org.eclipse.jst.jsf.validation.internal.el/debug/jspsemanticsvalidator"); //$NON-NLS-1$
DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
}
private final static ElementToTagIdentifierMapping elem2TagIdMapper = new ElementToTagIdentifierMapping();
private IDocument fDocument;
private int containmentValidationCount; // = 0;
/* (non-Javadoc)
* @see org.eclipse.jst.jsp.core.internal.validation.JSPValidator#validateFile(org.eclipse.core.resources.IFile, org.eclipse.wst.validation.internal.provisional.core.IReporter)
*/
protected void validateFile(IFile file, IReporter reporter) {
IStructuredModel model = null;
if (DEBUG)
System.out.println("executing JSPSemanticsValidator.validateFile");
try {
model = StructuredModelManager.getModelManager().getModelForRead(file);
if (model instanceof DOMModelForJSP)
{
ValidationPreferences prefs= new ValidationPreferences(JSFCorePlugin.getDefault().getPreferenceStore());
prefs.load();
DiagnosticFactory diagnosticFactory = new DiagnosticFactory();
// zero the containment validation count for each mondel
containmentValidationCount = 0;
DOMModelForJSP jspModel = (DOMModelForJSP) model;
IStructuredDocument structuredDoc = jspModel.getStructuredDocument();
IStructuredDocumentRegion curNode = structuredDoc.getFirstStructuredDocumentRegion();
while (null != curNode && !reporter.isCancelled()) {
if (curNode.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN )
{
validateTag(curNode, reporter, file, false, prefs, diagnosticFactory);
}
curNode = curNode.getNext();
}
}
}
catch (CoreException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
catch (IOException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
finally
{
if (null != model)
model.releaseFromRead();
// zero the containment count before exit
containmentValidationCount = 0;
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#validate(org.eclipse.jface.text.IRegion, org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
*/
public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
if (DEBUG)
System.out.println("exec JSPSemanticsValidator.validateRegion");
ValidationPreferences prefs = new ValidationPreferences(JSFCorePlugin.getDefault().getPreferenceStore());
prefs.load();
DiagnosticFactory diagnosticFactory = new DiagnosticFactory();
if (fDocument instanceof IStructuredDocument) {
IStructuredDocument sDoc = (IStructuredDocument) fDocument;
IStructuredDocumentRegion[] regions = sDoc.getStructuredDocumentRegions(dirtyRegion.getOffset(), dirtyRegion.getLength());
if (regions != null){
validateTag(regions[0], reporter, getFile(helper), true, prefs, diagnosticFactory);
}
}
}
private IFile getFile(IValidationContext helper) {
String[] uris = helper.getURIs();
IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
if (uris.length > 0)
return wsRoot.getFile(new Path(uris[0]));
return null;
}
/**
* Validates a JSP tag.
*
* Currently only attribute values with supplied annotation meta-data is being validated.
* Also, only JSF EL is being validated and not JSP EL.
*
* This method may be extended in the future to validate tag semantics an other cross attribute
* validations.
*
* @param container
* @param reporter
* @param file
* @param isIncremental -- true if this validation is "as you type"
*
*/
private void validateTag(ITextRegionCollection container, IReporter reporter, IFile file, boolean isIncremental, ValidationPreferences prefs, DiagnosticFactory diagnosticFactory)
{
ITextRegionCollection containerRegion = container;
Iterator regions = containerRegion.getRegions().iterator();
ITextRegion region = null;
String uri = null;
String tagName = null;
String attrName = null;
while (regions.hasNext() && !reporter.isCancelled())
{
region = (ITextRegion) regions.next();
String type = region.getType();
IDOMContextResolver resolver = null;
ITaglibContextResolver tagLibResolver = null;
if (type != null && (type == DOMRegionContext.XML_TAG_NAME || type == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE))
{
IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE.getContext(((IStructuredDocumentRegion)containerRegion).getParentDocument(), containerRegion.getStartOffset() + region.getStart());
resolver = IStructuredDocumentContextResolverFactory.INSTANCE.getDOMContextResolver(context);
if (type == DOMRegionContext.XML_TAG_NAME)
{
tagLibResolver = IStructuredDocumentContextResolverFactory.INSTANCE.getTaglibContextResolver(context);
Node node = resolver.getNode();
tagName = resolver.getNode().getLocalName();
uri = tagLibResolver.getTagURIForNodeName(resolver.getNode());
if (node instanceof Element && uri != null)
{
validateContainment((Element)node, uri, tagName, reporter, file, context);
}
if (DEBUG)
System.out.println(addDebugSpacer(1)+"tagName= "+ (tagName!= null ? tagName : "null") +": uri= "+(uri != null ? uri : "null") );
}
else if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
{
attrName = resolver.getNode().getNodeName();
if (DEBUG)
System.out.println(addDebugSpacer(2)+"attrName= "+(attrName != null ? attrName : "null" ));
if (uri != null && tagName != null)
{
// TODO: validateAttribute(context, region, uri, resolver.getNode(), file);
}
}
else if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
{
final String attributeVal =
resolver.getNode().getNodeValue();
// if there's elText then validate it
// TODO: this approach will fail with mixed expressions
if (!checkIfELAndValidate(region,
context,
uri,
tagName,
attrName,
attributeVal,
isIncremental,
reporter,
file,
prefs,
diagnosticFactory)
)
{
// else validate as static attribute value
if (DEBUG)
System.out.println(addDebugSpacer(3)+"attrVal= "+(attributeVal != null ? attributeVal : "null") );
if (uri != null && tagName != null && attrName != null)
validateAttributeValue(context, uri, tagName, attrName, attributeVal, reporter, file);
}
}
}
}
}
/**
* Checks the region to see if it contains an EL attribute value. If it
* does, validates it
* @return true if validated EL, false otherwise
*/
private boolean checkIfELAndValidate(ITextRegion region,
IStructuredDocumentContext context,
String uri,
String tagName,
String attrName,
String attrValue,
boolean isIncremental,
IReporter reporter,
IFile file,
ValidationPreferences validationPrefs,
DiagnosticFactory diagnosticFactory)
{
if (region instanceof ITextRegionCollection) {
ITextRegionCollection parentRegion = ((ITextRegionCollection) region);
if (parentRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
{
// look for attribute pattern "#{}"
// TODO: need to generalize this for RValue concatenation
final ITextRegionList regionList = parentRegion.getRegions();
if (regionList.size() >= 4)
{
ITextRegion openQuote = regionList.get(0);
ITextRegion openVBLQuote = regionList.get(1);
if ( (openQuote.getType() == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE
|| openQuote.getType() == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_SQUOTE)
&& (openVBLQuote.getType() == DOMJSPRegionContexts.JSP_VBL_OPEN))
{
// we appear to be inside "#{", so next should be a VBL_CONTENT if there's anything
// here to validate
final ITextRegion content = regionList.get(2);
if (content.getType() == DOMJSPRegionContexts.JSP_VBL_CONTENT)
{
final int contentStart =
parentRegion.getStartOffset(content);
final IStructuredDocumentContext elContext =
IStructuredDocumentContextFactory.INSTANCE.
getContext(context.getStructuredDocument(),
contentStart);
final String elText = parentRegion.getText(content);
if (DEBUG)
System.out.println(addDebugSpacer(3)+"EL attrVal= "+elText);
// EL validation is user configurable because
// it can be computationally costly.
if (checkShouldValidateEL(validationPrefs, isIncremental))
{
List elVals = MetaDataEnabledProcessingFactory.getInstance().getAttributeValueRuntimeTypeFeatureProcessors(IValidELValues.class, elContext, uri, tagName, attrName);
validateELExpression(context,
elContext,
elVals,
attrValue,
elText,
reporter,
file,
validationPrefs.getElPrefs());
}
}
else if (content.getType() == DOMJSPRegionContexts.JSP_VBL_CLOSE)
{
final int offset = parentRegion.getStartOffset(openVBLQuote)+1;
final int length = 2;
// detected empty EL expression
IMessage message = ValidationMessageFactory.createFromDiagnostic(
diagnosticFactory.create_EMPTY_EL_EXPRESSION(),
offset, length, file, validationPrefs.getElPrefs());
reportFinding(reporter, message);
}
boolean foundClosingQuote = false;
for (int i = 2; !foundClosingQuote && i < regionList.size(); i++)
{
ITextRegion searchRegion = regionList.get(i);
if (searchRegion.getType() == DOMJSPRegionContexts.JSP_VBL_CLOSE)
{
foundClosingQuote = true;
}
}
if (!foundClosingQuote)
{
int offset = context.getDocumentPosition()+1;
int length = parentRegion.getText().length();
reportFinding(reporter,
ValidationMessageFactory.
createFromDiagnostic(
diagnosticFactory.create_MISSING_CLOSING_EXPR_BRACKET(),
offset, length, file, validationPrefs.getElPrefs()));
}
return true;
}
}
}
}
return false;
}
private void validateELExpression(IStructuredDocumentContext context,
IStructuredDocumentContext elContext,
List elVals,
String attributeVal,
String elText,
IReporter reporter,
IFile file,
ELValidationPreferences prefs)
{
//Call EL validator which will perform at least the syntactical validation
final ELExpressionValidator elValidator =
new ELExpressionValidator(elContext, elText,file,prefs);
elValidator.validateXMLNode();
elValidator.reportFindings(this, reporter);
CompositeType exprType = elValidator.getExpressionType();
if (exprType != null)
{
for (Iterator it=elVals.iterator();it.hasNext();){
IValidELValues elval = (IValidELValues)it.next();
CompositeType expectedType;
IMessage message = null;
try {
expectedType = elval.getExpectedRuntimeType();
if (expectedType != null)
{
Diagnostic status = TypeComparator.calculateTypeCompatibility
(expectedType, exprType);
if (status.getSeverity() != Diagnostic.OK){
message = createValidationMessage(context, attributeVal, getSeverity(status.getSeverity()), status.getMessage(), file);
}
}
} catch (ELIsNotValidException e) {
message = createValidationMessage(context, attributeVal, IMessage.NORMAL_SEVERITY, e.getMessage(), file);
}
if (message != null) {
reportFinding(reporter, message);
}
}
}
}
// private void validateAttribute(IStructuredDocumentContext context, ITextRegion region, String uri, Node attr, IFile file) {
//Not doing anything until the resolver can help me
//validate that attribute can be part of the tag
// ITaglibContextResolver tagLibResolver = IStructuredDocumentContextResolverFactory.INSTANCE.getTaglibContextResolver(context);
// if (tagLibResolver.getTagURIForNodeName(attr) == null){
// System.out.println("not ok: "+attr.getNodeName());
// }
// else
// System.out.println("ok");
// }
/**
* Validates an attribute value in context using the JSF metadata processing framework
*
* @param context
* @param region
* @param uri
* @param tagName
* @param attrName
* @param attributeVal
* @param reporter
* @param file
*/
private void validateAttributeValue(IStructuredDocumentContext context, String uri, String tagName, String attrName, String attributeVal, IReporter reporter, IFile file) {
List vv = MetaDataEnabledProcessingFactory.getInstance().getAttributeValueRuntimeTypeFeatureProcessors(IValidValues.class, context, uri, tagName, attrName);
if (!vv.isEmpty()){
for (Iterator it = vv.iterator();it.hasNext();){
IValidValues v = (IValidValues)it.next();
if (attributeVal == null) attributeVal = "";//ensure to be non-null
if (!v.isValidValue(attributeVal.trim())){
if (DEBUG)
System.out.println(addDebugSpacer(4)+"NOT VALID ");
for (Iterator msgs = v.getValidationMessages().iterator();msgs.hasNext();){
IValidationMessage msg = (IValidationMessage)msgs.next();
IMessage message = createValidationMessage(context, attributeVal, getSeverity(msg.getSeverity()), msg.getMessage(), file);
if (message != null) {
reportFinding(reporter, message);
}
}
}
else
if (DEBUG)
System.out.println(addDebugSpacer(5) + "VALID ");
}
}
else if (DEBUG)
System.out.println(addDebugSpacer(4)+"NO META DATA ");
}
private IMessage createValidationMessage(IStructuredDocumentContext context, String attributeValue, int severity, String msg, IFile file){
IMessage message = new LocalizedMessage(severity, msg, file);
if (message != null) {
final int start = context.getDocumentPosition() + 1;
final int length = attributeValue.length();
int lineNo = 0;
try {
lineNo = context.getStructuredDocument().getLineOfOffset(start);
} catch (BadLocationException e) {
// TODO: C.B why need line number? Length and offset should be
// sufficient
}
message.setLineNo(lineNo);
message.setOffset(start);
message.setLength(length);
}
return message;
}
/**
* Maps IStatus codes to IMessage severity
* @param IStatus codesseverity
* @return IMessage severity
*/
private int getSeverity(int severity) {
switch (severity){
case IStatus.ERROR:
return IMessage.HIGH_SEVERITY;
case IStatus.WARNING:
return IMessage.NORMAL_SEVERITY;
case IStatus.INFO:
return IMessage.LOW_SEVERITY;
}
return IMessage.NORMAL_SEVERITY;
}
/* (non-Javadoc)
* @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#connect(org.eclipse.jface.text.IDocument)
*/
public void connect(IDocument document) {
fDocument = document;
containmentValidationCount = 0; // ensure is zeroed before we start
}
/* (non-Javadoc)
* @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#disconnect(org.eclipse.jface.text.IDocument)
*/
public void disconnect(IDocument document) {
containmentValidationCount = 0; // ensure is zeroed when we are finished
}
private String addDebugSpacer(int count){
String TAB = "\t";
StringBuffer ret = new StringBuffer("");
for(int i=0;i<=count;i++){
ret.append(TAB);
}
return ret.toString();
}
/**
* @param isIncremental -- true if this is "as-you-type" validation, false
* if this is "Build" or "Run Validation" validation
* @return true if user preferences say we should do EL validation,
* false otherwise
*/
private boolean checkShouldValidateEL(ValidationPreferences prefs, boolean isIncremental)
{
prefs.load();
if (isIncremental)
{
return prefs.getElPrefs().isEnableIncrementalValidation();
}
return prefs.getElPrefs().isEnableBuildValidation();
}
private void validateContainment(Element node, String uri, String tagName, IReporter reporter, IFile file, IStructuredDocumentContext context)
{
// don't validate JSP fragments since the necessary containment may existing
// in the JSP files that include them
// also only validate the first instance of containment violation in a file
if (JSPUtil.isJSPFragment(file) || containmentValidationCount > 0)
{
return;
}
final ITaglibDomainMetaDataModelContext modelContext =
TaglibDomainMetaDataQueryHelper.createMetaDataModelContext(file.getProject(), uri);
final Entity entity =
TaglibDomainMetaDataQueryHelper.getEntity(modelContext, tagName);
if (entity != null)
{
final Trait trait =
TaglibDomainMetaDataQueryHelper.getTrait
(entity, "containment-constraint");
if (trait != null)
{
final ContainsTagConstraint tagConstraint =
(ContainsTagConstraint) trait.getValue();
final String algorithm = tagConstraint.getSetGenerator().getAlgorithm();
// TODO: need generalized factory mechanism for registering and constructing
// algorithms.
if (!"xpath".equals(algorithm))
{
return;
}
final String expr = tagConstraint.getSetGenerator().getExpression();
// TODO: optimize on the expression and cache for reuse
final XPathMatchingAlgorithm xpathAlg =
new XPathMatchingAlgorithm(expr);
AxiomaticSet set = null;
try
{
set = xpathAlg.evaluate(node);
// map dom nodes to tag identifiers
set = elem2TagIdMapper.map(set);
}
catch(InvalidExpressionException e)
{
JSFCorePlugin.log(e, "Problem with expression: "+expr+" on node "+node);
return;
}
catch (EvaluationException e)
{
JSFCorePlugin.log(e, "Problem evaluating expression: "+expr+" on node "+node);
return;
}
final TagSet constraintData = tagConstraint.getSatisfiesSet();
final AxiomaticSet constraintSet = new ConcreteAxiomaticSet();
for (final Iterator it = constraintData.getTags().iterator(); it.hasNext();)
{
final TagId tagId = (TagId) it.next();
constraintSet.add(TagIdentifierFactory.createJSPTagWrapper(tagId.getUri(), tagId.getName()));
}
final MemberConstraint memberConstraint = new MemberConstraint(constraintSet);
final Diagnostic diag = memberConstraint.isSatisfied(set);
if (diag.getSeverity() != Diagnostic.OK)
{
containmentValidationCount++; // found a violation
final String messagePattern = "Tag {0} is missing required parent tag \"{1}\" ({2})";
List data = diag.getData();
for (Iterator it = data.iterator(); it.hasNext();)
{
TagIdentifier missingParent = (TagIdentifier) it.next();
IMessage message =
createTagValidationMessage(context, node.getNodeName(),
IMessage.NORMAL_SEVERITY,
MessageFormat.format(messagePattern, new Object[]{node.getNodeName(), missingParent.getTagName(), missingParent.getUri()})
, file);
reportFinding(reporter, message);
}
}
}
}
}
/**
* @return the test interface
*/
public IJSPSemanticValidatorTest getTestInterface()
{
return new IJSPSemanticValidatorTest()
{
public void validateContainment(Element node, String uri,
String tagName, IReporter reporter, IFile file,
IStructuredDocumentContext context) {
JSPSemanticsValidator.this.validateContainment(node, uri, tagName, reporter, file, context);
}
};
}
// TODO: need a diagnostic factory
private IMessage createTagValidationMessage(IStructuredDocumentContext context, String attributeValue, int severity, String msg, IFile file)
{
IMessage message = new LocalizedMessage(severity, msg, file);
final int start = context.getDocumentPosition();
final int length = attributeValue.length();
message.setOffset(start);
message.setLength(length);
return message;
}
private void reportFinding(IReporter reporter, IMessage message)
{
if ((message.getSeverity() & IMessage.ALL_MESSAGES) != 0)
{
reporter.addMessage(this, message);
}
}
}