/* * 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. */ /* * $Id$ */ /* * * XHTFileCheckService.java * */ package org.apache.qetest.xsl; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import org.apache.qetest.CheckService; import org.apache.qetest.ConsoleLogger; import org.apache.qetest.Logger; import org.apache.qetest.XMLFileLogger; /** * Uses an XML/HTML/Text diff comparator to check or diff two files. * @see #check(Logger logger, Object actual, Object reference, String msg, String id) * @author Shane_Curcuru@lotus.com * @version $Id$ */ public class XHTFileCheckService implements CheckService { /** XHTComparator tool to diff two files. */ protected XHTComparator comparator = new XHTComparator(); /** Stores last checkFile calls printed output. */ private StringWriter sw = null; /** * Compare two objects for equivalence, and return appropriate result. * Note that the order of actual, reference is important * important in determining the result. *
*
* StylesheetTestlet match16.xsl(null)
* XHTFileCheckService threw: java.io.IOException: The process cannot access the file because it is being used by another process
* java.io.IOException: The process cannot access the file because it is being used by another process
* at java.io.Win32FileSystem.canonicalize(Native Method)
* etc...
* XHTFileCheckService files were not equal
*
*
*
* @param logger to dump any output messages to
* @param name of actual (current) File to check
* @param name of reference (gold, or expected) File to check against
* @param msg comment to log out with this test point
* @param id to log out with this test point
* @param additional log info from PrintWriter/StringWriter
*/
protected void logFileCheckElem(Logger logger,
String actualFile, String referenceFile,
String msg, String id, String logs)
{
Hashtable attrs = new Hashtable();
attrs.put("actual", actualFile);
attrs.put("reference", referenceFile);
attrs.put("reportedBy", "XHTFileCheckService");
try
{
attrs.put("baseref", System.getProperty("user.dir"));
}
catch (Exception e) { /* no-op, ignore */ }
String elementBody = msg + "(" + id + ") \n" + logs;
// HACK: escapeString(elementBody) so that it's legal XML
// for cases where we have XML output. This isn't
// necessarily a 'hack', I'm just not sure what the
// cleanest place to put this is (here or some sort
// of intelligent logic in XMLFileLogger)
elementBody = XMLFileLogger.escapeString(elementBody);
logger.logElement(Logger.STATUSMSG, "fileCheck", attrs, elementBody);
}
/**
* Compare two objects for equivalence, and return appropriate result.
*
* @see #check(Logger logger, Object actual, Object reference, String msg, String id)
* @param logger to dump any output messages to
* @param actual (current) File to check
* @param reference (gold, or expected) File to check against
* @param description of what you're checking
* @param msg comment to log out with this test point
* @return Logger.*_RESULT code denoting status; each method may
* define it's own meanings for pass, fail, ambiguous, etc.
*/
public int check(Logger logger, Object actual, Object reference,
String msg)
{
return check(logger, actual, reference, msg, null);
}
/**
* Prefix to all attrs we understand.
* Note: design-wise, it would be better to have these constants
* in the XHTComparator class, since we know we're tightly bound
* to them anyways, and they shouldn't really be bound to us.
* But for my current purposes, it's simpler to put them here
* for documentation purposes.
*/
public static final String URN_XHTFILECHECKSERVICE = "urn:XHTFileCheckService:";
/** Whether whitespace differences will cause a fail or not. */
public static final String ALLOW_WHITESPACE_DIFF = URN_XHTFILECHECKSERVICE + "allowWhitespaceDiff";
/** If we should call parser.setValidating(). */
public static final String SETVALIDATING = URN_XHTFILECHECKSERVICE + "setValidating";
/** If we should call parser.setIgnoringElementContentWhitespace(). */
public static final String SETIGNORINGELEMENTCONTENTWHITESPACE = URN_XHTFILECHECKSERVICE + "setIgnoringElementContentWhitespace";
/** If we should call parser.setExpandEntityReferences(). */
public static final String SETEXPANDENTITYREFERENCES = URN_XHTFILECHECKSERVICE + "setExpandEntityReferences";
/** If we should call parser.setIgnoringComments(). */
public static final String SETIGNORINGCOMMENTS = URN_XHTFILECHECKSERVICE + "setIgnoringComments";
/** If we should call parser.setCoalescing(). */
public static final String SETCOALESCING = URN_XHTFILECHECKSERVICE + "setCoalescing";
/**
* Whether whitespace differences will cause a fail or not.
* setAttribute("allow-whitespace-diff", true|false)
* true=whitespace-only diff will pass;
* false, whitespace-only diff will fail
*/
protected boolean allowWhitespaceDiff = false; // default; backwards compatible
/**
* Properties/Hash of parser-like attributes that have been set.
*/
protected Properties attributes = null;
/**
* Allows the user to set specific attributes on the testing
* utility or it's underlying product object under test.
*
* Supports basic JAXP DocumentBuilder attributes, plus our own
* ALLOW_WHITESPACE_DIFF attribute.
*
* @param name The name of the attribute.
* @param value The value of the attribute.
* @throws IllegalArgumentException thrown if the underlying
* implementation doesn't recognize the attribute and wants to
* inform the user of this fact.
*/
public void setAttribute(String name, Object value)
throws IllegalArgumentException
{
// Check for our own attributes first
if (ALLOW_WHITESPACE_DIFF.equals(name))
{
try
{
allowWhitespaceDiff = (new Boolean((String)value)).booleanValue();
}
catch (Throwable t)
{
// If it's an illegal value or type, ignore it
}
}
else
{
if (null == attributes)
{
attributes = new Properties();
}
attributes.put(name, value);
}
}
/**
* Allows the user to set specific attributes on the testing
* utility or it's underlying product object under test.
*
* This method should attempt to set any applicable attributes
* found in the given attrs onto itself, and will ignore any and
* all attributes it does not recognize. It should never
* throw exceptions. This method will overwrite any previous
* attributes that were set.
* This method will only set values that are Strings findable
* by the Properties.getProperty() method.
*
* Future Work: this could be optimized by simply setting our
* Properties block to default from the passed-in one, but for
* now instead it only copies over the explicit values that
* we think are applicable.
*
* @param attrs Props of various name, value attrs.
*/
public void applyAttributes(Properties attrs)
{
attributes = null;
for (Enumeration names = attrs.propertyNames();
names.hasMoreElements(); /* no increment portion */ )
{
String key = (String)names.nextElement();
if (key.startsWith(URN_XHTFILECHECKSERVICE))
{
setAttribute(key, attrs.getProperty(key));
}
}
}
/**
* Allows the user to retrieve specific attributes on the testing
* utility or it's underlying product object under test.
*
* See applyAttributes for some limitations.
*
* @param name The name of the attribute.
* @return value of supported attributes or null if not recognized.
* @throws IllegalArgumentException thrown if the underlying
* implementation doesn't recognize the attribute and wants to
* inform the user of this fact.
*/
public Object getAttribute(String name)
throws IllegalArgumentException
{
// Check for our own attributes first
if (ALLOW_WHITESPACE_DIFF.equals(name))
{
return new Boolean(allowWhitespaceDiff);
}
else if (null != attributes)
{
return attributes.get(name);
}
else
return null;
}
/**
* Description of what this testing utility does.
*
* @return String description of extension
*/
public String getDescription()
{
return ("Uses an XML/HTML/Text diff comparator to check or diff two files.");
}
/**
* Gets extended information about the last check call.
* This info is filled in for every call to check() with brief
* descriptions of what happened; will return
* XHTFileCheckService-no-info-available if
* check() has never been called.
* @return String describing any additional info about the
* last two files that were checked
*/
public String getExtendedInfo()
{
if (sw != null)
return sw.toString();
else
return "XHTFileCheckService-no-info-available";
}
/**
* Main method to run test from the command line - can be left alone.
* @param args command line argument array
*/
public static void main(String[] args)
{
if (args.length < 2)
{
System.out.println(" Please provide two files to compare");
}
else
{
ConsoleLogger log = new ConsoleLogger();
XHTFileCheckService app = new XHTFileCheckService();
System.out.println("\nThank you for using XHTFileCheckService");
System.out.println( app.getDescription() );
System.out.println("We hope your results are satisfactory");
System.out.println("\n" + args[0] + " " + args[1]);
File fAct = new File(args[0]);
File fExp = new File(args[1]);
try
{
app.check(log, fAct, fExp, "Check");
}
catch (Exception e)
{
System.out.println ("main() caught unexpected Exception");
}
}
}
} // end of class XHTFileCheckService