Version 1.4b27[TEST-8] of 12-Nov-2012
- Altered the signatures of the two
QwicapServlet.initmethods such that both are allowed to throw the standardServletException, like any other servlet. - Corrected a crashing bug that appeared when running Qwicap under Apple's Java 1.6 distribution for Mac OS X 10.8.2. The problem was the stack size of the small entropy-generating threads of the pseudo random number generator. Because the threads are very simple, their stack size was set at 64 KB, rather than allowing a stack of an unknown size (but somewhere around 1.5 MB) to be allocated by default. That 64 KB stack had been fine, but now results in crashes. Consequently, the entropy thread stack sizes have been doubled to 128 KB, and testing shows that to be sufficient. There's no way to be certain that this will always be an adequate stack size, or that it is currently sufficient for all platforms (though there've been no problem reports), so this issue can only be provisionally designated as fixed.
- Small change to the
StackTraceclass to make its output more consistent with Java's, but without any of Java's bad habits, like stacktrace truncation. - Corrected a grammatical error in the
Results.setAttributesJavadocs. - Improvements to the
FormControlInfoJavadocs, along with a further tweak to allow for the fact that the javadoc generator, either by default, or in all cases, doesn't produce output that can handle all UTF-8 characters properly, probably because the awful HTML it generates does not specify the character set/encoding employed in its HTML output. - Some improved features, like the ability of the
FormInputRejectionHelperclass to mark unlabelled text fields (both "input" and "textarea") in red when they supply bad input, so that the field that is the source of the bad input can be made obvious to the user even in the absence of labels. - Made an accumulation of small changes throughout the code base largely due to various
utility classes, which will eventually be made available as stand-alone libraries, being
moved into packages of their own, thus changing
importstatements wherever they are used in Qwicap classes. - Corrected an oversight in the date format used by the reports produced by the
ServiceDataRecorderclass. It had been using hours expressed as 0-11 along with an AM/PM indicator. However, in the presence of an AM/PM indicator, hours should be expressed as 1-12. And now they are. - Improvements to the wording and look of the Qwicap "dialog boxes" that are displayed when a web application session terminates for any reason.
- Reduced access from
publictoprotectedfor the internal "IntraElementContentMatchclass' constructor. (The class has to bepublicbecause uses of it span package boundaries, but it is not part of the Qwicap public API.) - Various improvements to the Javadocs.
- Reduced logging priority from "SEVERE" to "WARNING" for the log message: "The character set of the form data set could not be identified; defaulting to ISO-8859-1."
- Corrected a bug in the plural numeric "get" methods of the
Qwicapclass, for examplegetInts,getDoubles, etc. The bug was that, when theAllowedToBeBlankparameter wastrue, a blank input value was not always being replaced with the corresponding value from theDefaultValuesparameter, and would instead cause the input to be rejected. - Minor additions and modifications to the "qwicap.css" style sheet to support new, but not yet finished, user input error reporting capabilities. Changed the name of the style sheet used by the various Qwicap problem pages (for cases like a crash, unexpected exit, or app restart) to something more general to avoid confusing myself. Altered the CSS reference in the problem pages accordingly.
- Added the missing
Qwicap.getStringsmethods. (This is a historical oversight caused by the fact that all of the numeric retrieval methods could easily be "pluralized", because they all built on a single method for retrieving and validating multiple numeric values. Non-numeric retrieval methods couldn't build on that common numeric retrieval method, and were therefore left-out of the "pluralization" effort.) Still required: plural forms of theQwicap.getBooleanmethods. - Made the message in the "qwicap-exit.html" page more user friendly.
- Changed the access control modifier on the
BlockingDescriptionconstructor from "package" toprotected. - Added a
clonemethod to theALStackclass. Modified theremovemethod of theArrayIteratormethod such that it throws anUnsupportedOperationExceptionwhen invoked, instead of doing nothing at all. - Minor refinements to the Ant build scripts.
- Added a typecast to a
FormDataSet.addDatainvocation in theFormclass in order to avoid a compiler warning. - In the
i18nDocumentAccessorclass, tweaked a variable type fromClasstoClass<?>to make IntelliJ IDEA's code sense checks happy.
Version 1.4b26 of 27-Apr-2011
- Extended the
Auth2Schemeinterface such that itsqwicapAuth2SchemeHitmethod now receives aFormDataSetinstance as its final parameter, in caseAuth2Schemeimplementations want to risk altering their behaviors based on user input (which could be bogus). Note: This extension alters the pre-existingAuth2Schemeinterface, and therefore breaks any existingAuth2Schemeimplementations. The fix is trivial, however: Add a parameter of typeFormDataSetto the end of the parameter lists of yourAuth2Scheme.qwicapAuth2SchemeHitmethods. Since the parameter didn’t exist before now, and pre-existingAuth2Schemeimplementations therefore have no use for it, they can simply ignore it. So, it’s a one line fix, with no logic changes. Trivial. - The
Auth2SchemeReply.qwicapShouldDiscardThisSessionmethod has Javadocs, at long last. For some reason, it had escaped being documented until now. - Changed the default URI attribute separator used by the
FormDataSet.toWWWFormURLEncoded...methods from a semicolon (';') to an ampersand ('&'), because too much software is ignorant of the semicolon recommendation (see section "B.2.2 Ampersands in URI attribute values" of the HTML 4.01 Specification, where it states "We recommend that HTTP server implementors, and in particular, CGI implementors support the use of ';' in place of '&' to save authors the trouble of escaping '&' characters [....]"). This reverses a change made in Qwicap version 1.4b13. - Altered the
QwicapServlet,QwicapApplicationServicesandQwicapclasses to pass arguments to a web application's entry point (its "public static void main(String[] args)" method) for the first time. The first argument is the deployed name of the web application. The arguments that follow are alternating names and values from, first, the "context-param", and then the "init-param", elements in the web application deployment descriptor ("web.xml" file). The order in which the name and value pairs obtained from the "context-param" and "init-param" elements appear in the argument list is undefined, because the order of retrieval by theServletContext.getInitParameterNamesandServlet.getInitParameterNamesmethods is unspecified. However, this much can be said: In the argument list, the names and values obtained from "context-param" elements will appear prior to the names and values obtained from the "init-param" elements. - The Javadocs associated with the
Qwicap.rejectInputmethods have been revised in order to explicitly describe their blocking behavior, and the flow control imposed on the caller when the methods unblock and always throw aQwicapExceptionin order to restart the caller’s input processing logic (an outcome ensured by the use of the Qwicap “prompt pattern”). This does not represent a change in the behavior of Qwicap (it has always worked this way). It is merely an improvement to the Javadocs that may be of some assistance to developers. - Improved some of the grammar in the Javadoc for the
Qwicap.convertSubmitButtonsToInputsmethod. - Added the
edu.utexas.its.eis.tools.qwicap.Versionclass to provide the current version and build number information (see theVersion.getStringstatic method), so that that information is no longer stored in theQwicapclass (it can still be accessed through theQwicap.getVersionStringmethod, however). Updated the Ant build script, "build.xml", to automatically update the version information in theVersionclass, including its Javadocs, rather than modifying theQwicapclass. - Found that the "qwicap-crash.html" page was using a different HTML element class to identify elements (typically "span" tags) whose contents should be replaced with the "incident codes" used to opaquely identify individual errors. It now uses the same HTML element class, "qwicap-incident-code", that is used in all other pages.
- Eliminated the code that set the URL of the "action" attributes of the "form"
elements in the pages used by the
QwicapServletclass’ internal methodsshowCrashPage(page: "qwicap-crash.html"),showExitPage(page: "qwicap-exit.html"), andshowRestartPage(page: "qwicap-restart.html"). While it seems logical to set those attribtues to point to the current web application in cases where they're simply left blank (which they are in the default pages embedded in Qwicap), it so happens that by virtue of being blank, they automatically refer to the current web application. Therefore, what seemed like a useful feature actually turned out to be either unnecessary, or counterproductive, and therefore that feature has been eliminated. The "action" attributes of the "form" elements in those pages (or any developer-supplied substitute pages) will now be left unmodified. - Ant build file ("build.xml") improvements, including: updated library Javadoc URLs (Oracle has been relocating Java documentation); the ability to keep the "dist" directory and its contents between builds so that binaries (JARs) can be included in the repository; and the generation of compressed JARs, in all cases.
- Moved the
XMLCharacterSetDetectorclass, and all associated classes, into theedu.utexas.its.eis.tools.qwicap.template.xml.util.xcsdpackage, so that it can be built as a stand-alone library for use independent of Qwicap. (It is built using the new "build-xcsd.xml" Ant script, which is automatically run by the "project-dist" task of the overall Qwicap build script, "build.xml".) - For XML that includes a byte-order-mark (BOM), added a test for consistency between the character set identified by the BOM and the encoding identified in the XML declaration (if any). If they are found to be inconsistent, a "SEVERE" log message is generated, and the markup is read using the character set identified by the BOM.
- Added some extra, apparently redundant, but (at worst) harmless, code to remove the registration of Qwicap’s “Rule30” secure pseudo random number generator. Since that registration creates the potential for a memory leak in a web application server, ensuring that the registration is removed when Qwicap is shutdown is important enough to merit some apparently redundant code.
- Modified the
Rule30RandomProvider.engineGenerateSeedmethod such that it actually generates a new seed value using the internalEntropyclass, rather than using a stored instance of theRule30RandomPRNG to generate the seed value. - Generally improved the internal
Entropyclass that provides seeds for theRule30RandomPRNG class. Also, memory use has been reduced, timings have been adjusted to allow for microsecond counters (like the one in Java 6 on Mac OS X 10.6.1) that don't use their full precision, and a sign-extension issue has been corrected. Rule30RandomProvidernow registers the Qwicap’s Rule 30 PRNG provider with a version number corresponding to Qwicap’s major and minor version numbers (1.4 at the moment).- Minor optimizations to the Rule 30 pseudo-random number generator code.
- The internal
edu.utexas.its.eis.tools.qwicap.servlet.QwicapGlobalServicesclass now logs all Security Providers at the "FINE" level. - Added
@Overrideannotations throughout the code to improve maintainability by making it possible for IDEs and the Java compiler to catch mistakes to which they would otherwise have been oblivious. - Improved the operation of the
FormDataSetFilterResponse.runmethod (and the non-public class,FilterActionRun, which implements that functionality) by making them indifferent to an empty page stack. Thus,FormDataSetFilterResponse.runcan operate correctly before a web application has displayed any pages. - Improved the Javadocs for the
FormDataSetFilterResponseclass. - Modified the
Form(Match)constructor to verify that the suppliedMatchinstance refers to a "form" element. If not, aFormNotFoundExceptionis thrown. - The
Form.getDataSetmethod will now include a solitary "submit" control (whether it's an "input" or a "button" element), even if that control lacks a name. - Corrected a bug in the
Form.getControlValue(String)method which prevented it from returning the value of a "select" element when none of the child "option" elements had a "selected" attribute. In such cases, the first option is considered to be selected (and "successful") and it is now the value of the first option that is returned. Previously,nullwas returned. Added corresponding JUnit tests. - Corrected a bug in
Form.setControlValuethat sometimes prevented the previous value of the control from being cleared if it was a checkbox, radio button, or "select" control. - The
Form.printAllLabelsmethod has been deprecated, and a newForm.getControlsTablemethod has been added. (This continues the process of deprecating the old "print..." methods that were intended as developer aids, and replacing them with equivalent, or better, methods that don’t send their output to the console.) Significantly, the new method not only returns aMutableTableinstance containing the information (rather than printing anything), but it improves on the old method by: listing the controls in the order in which they are found in the markup; by including "select" controls (instead of just "option" controls); and by listing the name and value(s), if any, of each control. All subclasses of theTableclass will, of course, convert themselves to nicely formatted strings, so developers can print this table directly to the console, log it, etc. Since the table is mutable, developers may also sort its rows according to whatever columns are most important to them. - Updated the Javadoc class description for the
Formclass. - Improved the JUnit tests of the
Formclass. - Modified the
FormControlInfoclass such that the label string built for a control will never include information from any label-bearing element more than once. Such redundancy in labels was previously possible in the case of a form control located inside a "label" element whose "for" attribute referenced the control. Since a control located inside a label element is automatically associated with that label, associating the label with the control using a "for" attribute is redundant. However, it is possible, so the revisedFormControlInfoclass will detect and avoid such redundancy. - Improved the
FormControlInfo.toStringmethod. - Updated the URL production in the
FormInputRejectionHelperJUnitclass such that the URL produced for the "BaseDir" used in the test is produced using the approved means of invoking.toURI().toURL()on it, rather than just.toURL()which can produce invalid URLs. - Added support for UTF-32 (big- and little-endian) to the form data set character set detector code.
- Added
@Deprecatedannotations to theFormDataSetclass methods that were already marked as deprecated by their Javadocs. - Improved the Javadocs for several methods in the
FormDataSetclass. - Added the
Match.toFormmethod to increase parity between the functionality provide by theResultsclass and theMatchclass. (And also because the workaround,Match.toResults().toForm, looks ridiculous, which is a sign of poor API design.) - Modified the
Results.toFormmethod to search the list ofMatchobjects contained within theResultsobject and return aFormobject describing the first "form" element that is discovered. This represents a change of behavior. Previously, only the firstMatchobject in the list would be used in an attempt to create aFormobject. The virtue of this change is that it allows code likeMarkup.get("button[name=\"logout\"]").getAncestors().toForm()to work, which adds a convenient new way to locate a "form" element and to instantiate aFormobject to represent it. When no "form" element is present in theResultsobject, aFormNotFoundExceptionis thrown. (The behavior of the oldResults.getFormmethod remains unchanged for backward compatibility.) - The
Results.toFormmethod now allows itself to be invoked onImmutableMarkup. Previously, it could only be used onMutableMarkup. Needless to say, the methods of theFormclass that modify markup in any way will fail if used onImmutableMarkup, but the methods used merely to obtain data from markup will work. - The
Results.getFormmethod has been deprecated, and a more appropriately named method,Results.toForm, has taken its place. - Improved the Javadocs of
Results.getForm(deprecated) to document thatnullis returned when the first item in aResultsobject does not contain a reference to a "form" element. This has always been the behavior, but it was not documented. - Improved the Javadocs of the
Resultsclass, and marked its deprecated methods with@Deprecatedannotations. - The
FormNotFoundExceptionis now, officially, a part of Qwicap’s public API, and has been changed from a subclass ofQwicapExceptionto a subclass ofTagException. SinceTagExceptionis, itself, a subclass ofQwicapExceptionthe practical implications of this change should be nil. - Updated the internal
DocumentCacheclass to replace uses of the deprecatedFile.toURL()method, which can produce invalid URLs, withFile.toURI().toURL()invocations, which always produce valid URLs. No known bugs resulted from the prior implementation (the cases in whichFile.toURLcould produce invalid URLs shouldn’t have arisen withinDocumentCache), but the new implementation is assured to be correct, and is definitely the way to go forward. - Updated the internal
DocumentSourceclass to use new "Content-Type" parsing code, to keep MIME type and character set data separate, and to supply character set data to the XML parser, when available. (Otherwise, the XML parser continues to makes the character set determination itself.) - Added new document search logic that attempts to retrieve an otherwise unfound document as a resource of all of the application classes in the current stack trace.
- Updated the internal
LingeringDownloadablesclass to use a synchronizedHashMap, instead of the obsoleteHashtableclass. - Updated the internal
PageStackclass to improve the Javadocs, substitute a synchronizedHashMapfor a use of the obsoleteHashtableclass, and to add comments to the code, including comments that document the validity conditionals that depend on reference equality. - The
RangeListEnumeratormethodsnext,nextElementandnextRangehave been modified such that they throw theNoSuchElementExceptionwhen the end of the enumeration/iteration is passed. - In the
MutableMarkup.setCharacterSetmethod, improved the handling of the optional, XHTML-specific <meta http-equiv='Content-Type' content='subtype/type;charset=...'/> element. - Improved the
Pageclass to perform better handling of "Content-Type" information. - The complete range of syntax supported by the HTTP/MIME "Content-Type" is now supported. (To the extent that default character set identifications are document or protocol specific, document type and protocol specific classes have also been added to encapsulate that knowledge.) The "Content-Type" field seems to be widely and wildly underestimated in its complexity. One problem with it is that its capabilities are not set out in any single RFC, but are a combination of the capabilities discussed in RFCs 822, 2045, 2046, and 2616. This yields a field whose values can look like this: “text/plain; thought="Say \"Hello\" to Bob, please."; charset=us-ascii (Plain text)”, or can contain arbitrarily more data, quoted and unquoted, escaped and non-escaped, with comments and without, as appropriate to the standards and as necessary to the application. Any code that processes content types and cannot handle an example like that, is not standards-compliant. As far as I can tell, Qwicap is now capable of handling every aspect of content type specifiers. On the other hand, it was very difficult arriving at this level of understanding of all their possible formats, encodings, etc., and the possibility that there are details as yet overlooked cannot be entirely dismissed.
- Content read via HTTP whose "Content-Type" header identifies it as some type of text, but does not identify its character encoding, is treated as if it were encoded using IS0-8859-1, as the HTTP standard (RFC 2616) requires. However, that HTTP behavior is flatly contradicted by RFC 3023, section 3.1, when the content type is "text" and the subtype identifies the text as XML. In that case, RFC 3023 asserts precedence over RFC 2616 and requires that the default character encoding be regarded as "US-ASCII". Qwicap now respects both requirements, with RFC 3023 taking precedence over RFC 2616, when appropriate.
- If the
XMLDocumentclass, or any of its subclasses, is provided with access to a document through anInputStreamReader, the character set data in theInputStreamReaderis used as the identification of the document's character set. - Modified the
write(PrintWriter)methods ofMarkupandImmutableMarkupto return thePrintWriterthat is passed-in. - Improved the Javadoc for the
XMLDocument(Reader, long, String)constructor in order to clarify the meaning of theLengthHintparameter. - Added the
@Deprecatedannotation to theXMLCacheclass (its Javadoc has marked it as deprecated for years, so the deprecation is nothing new). Also added to the Javadocs a lengthy discussion about why this class was deprecated, and where Qwicap supplies automatic caching. BecauseXMLCacheis no longer considered to be part the Qwicap API (and hasn't been for some time), it is not included in the standard Javadocs. Interested people will need to refer to the source code for theXMLCacheclass to see the explanation. - Reduced the priority of the log messages that report when a valid "action" URL
cannot be constructed for a
FormDataSet. - Improvements to the
HTMLEntityCodecclass. - Corrected a typographical error in a log message in the
QwicapServletclass. - Removed contractions from a pair of exception messages in order to increase readability for people who are not native English speakers.
- Corrected grammatical errors in a few log messages.
- Upgraded the "table" library from version 1.0a46 to 1.0a50. Version 1.0a48 added the
ability to create tables from primitive arrays and arbitrary objects. Version 1.0a49
corrected a bug in padding table cells that contain other tables when the width of
any of those contained tables is one character less than the width of the column that
contains them. Version 1.0a50 fixes bugs associated with
nullnumeric and date values. - Upgraded the Apache Commons I/O library from version 1.4 to 2.0.1.
- Updated the "servlet-api.jar" library from whatever version was being used to the version supplied with Tomcat version 6.0.32.
Version 1.4b25 of 26-Sep-2008
- Added the
Form.getControlByIndexandForm.getControlByIndexAndValuemethods, for getting information about one control among many that share the same name. - Added the
FormDataSet.getActionURLandFormDataSet.setActionURLmethods. - Added the
Form.getAction,Form.getActionURL, andForm.getMethodmethods. - Added the
Form.getDataSet(IncludeSolitarySubmitControl)method for obtaining form data sets that optionally include the data (if any) provided by the form's "submit" button, provided that the form has only one "submit" button. - Added the
Form.getSubmitControlsmethod to return information about all of the "submit" controls in a form. - Modified the
Form.getControlValuesmethod to return values for graphical submit buttons ("input" controls of type "image"), when theIncludeSubmitControlsparameter istrue. The values returned for such controls are always two zeros ({ "0", "0" }). - Added two new
goodbyemethods:Qwicap.goodbye(String MIMEType, byte[] Data)andQwicap.goodbye(Downloadable). - Changed the "dialog box" pages that appear when a Qwicap application crashes, is supplied with obsolete parameters in the absence of a current session, etc. such that the "dialog box" will be "80ex" wide, rather than "60%" wide. This will give the dialogs a more reasonable appearance in very wide browser windows.
- Upgraded the Table library from version 1.0a45 to 1.0a46. The new version, by default, prevents tab characters from distorting tables by translating each one into as many as four spaces.
Version 1.4b24 of 7-Aug-2008
- Upgraded the Table library to version 1.0a45, which fixes a bug in its automatic storage unit formatter. Consequently, the Service Data Recorder's reports will no longer display the maximum size of the Java heap in Exabytes (EB). While the Exabyte value ("0.00 EB") included in the reports was correct, it was also thoroughly useless.
- Supplied some missing Javadocs for methods in the
FormDataSetclass. - Added the
FormControlValue.setValuesmethod, added theFormDataSet.setDatamethod, and improved theForm.getDataSetmethod. - Modified the code to use the new
ReadOnlyTableclass wherever possible, and made some other uses of the Table library more efficient.
Version 1.4b23 of 24-Jul-2008
- Corrected a bug in the internal
FormDataSet.getInputBytesmethod that could prevent some form data sets from being read completely. - Resolved floating-point precision issues in the
Qwicap.getFloatandQwicap.getDoublemethods. These methods have usedBigDecimalinternally for a long time, in order to deal with magnitude issues, but, until now, they had not used it in a way that also dealt with precision issues. - Replaced most uses of CSS pattern strings with pre-compiled, static
CSSPatternsobjects. This eliminates a lot of redundant CSS pattern parsing. - Added the missing
Match.get(CSSPatterns)method. - Removed obsolete code from the internal
ServiceDataclass. - Upgraded the "Table" library from version 1.0a39 to 1.0a42.
- Improved some logging messages.
Version 1.4b22 of 14-Jul-2008
- Upgraded the "Table" library from version 1.0a37 to 1.0a39.
- Various Javadoc improvements, including the documentation of the methods
of the interfaces in the "
edu.utexas.its.eis.tools.qwicap.template.xml.structure" package. - Removed the code (added in 1.4b21) for killing the MySQL JDBC driver's lingering
TimerTask, because killing that task didn't appear to make the web application'sClassLoaderany more likely to be garbage-collected. - Fixed an obscure bug in the internal
MatchEnumeratorclass that could cause aNullPointerExceptionto be thrown during someMatch.getTextinvocations. - Tweaks to the handling of namespaces in CSS selectors.
- CSS attribute selectors now support namespaces.
- Added two unit tests relating to operations on attribute names that include namespace prefixes.
- Corrected a bug in the internal
MuTagWithAttributesclass'toStringandwritemethods that could prevent the namespace prefix from being included in a tag's name when the markup is being handled in a namespace-aware manner. - Added two unit tests pertaining to the preservation of namespace prefixes in markup that's operating in a namespace-aware manner.
- Removed some obsolete "todo" items from the code. Removed old sections of commented-out code from various classes. Took advantage of terser syntax in some portions of the code.
- Improved the internal
TagHierarchyclass such that, when a namespace prefix on a tag's name cannot be resolved to a namespace declaration in the markup, the prefix ceases to be considered a namespace prefix and instead reverts to being considered a part of the tag's name. This prevents the prefix from being lost in some processes, notably the conversion of the tag from its immutable to its mutable form. - Changed the access control modifiers of the
QwicapServletmethodsdoGet,doHead, anddoPostto "protected".
Version 1.4b21 of 18-Jun-2008
- Corrected a mistake that would prevent a web application's
ClassLoaderfrom being garbage-collected. - The names of threads are now more descriptive, and a thread's name changes as its purpose changes.
- Corrected a bug that could cause a
NullPointerExceptionwhen rejecting bad input from a "form" element possessing an "input" control of type "submit" that has no name. - Corrected a bug that could corrupt the user's rejected input when that input was automatically embedded in the page from which it originated, so that the page could be sent back to the user for correction of the bad input.
- The
QwicapThreadPoolclass will now make a list-ditch effort to kill any lingering threads of classjava.util.TimerThreadthat it finds in its thread group. In practice, this problem arises due to a design issue in the MySQL JDBC driver, which creates a Timer named "MySQL Statement Cancellation Timer" that lingers even after all database connections have been closed. That lingering timer prevents the web application'sClassLoaderfrom being garbage-collected. - Added support for an experimental tool that monitors garbage collection
of
ClassLoaders associated with web applications. - Upgraded the "Table" library from version 1.0a36 to 1.0a37.
Version 1.4b20 of 3-Jun-2008
- Minor tweak to the private
geti18nServicesmethods of the classesResultsandSmartStringConverter. - Minor improvement of terminology in the Javadoc for the
Qwicap.getCurrrentInstancemethod.
Version 1.4b19 of 2-Jun-2008
- The portion of the
ClassPreloaderAndHolderclass that scans JARs in a web application for classes that need to be preloaded, now avoids trying to open some things that are obviously not JAR files, and recovers from arbitrary exceptions produced by theJarInputStreamclass. - Improvements to the implementation of the
geti18nServicesmethods of the classesResultsandSmartStringConverter. - Corrected an error in the Javadoc for the
Qwicap.getCurrrentInstancemethod. - Corrected a typographical error in a log message.
- Removed some old, commented-out code from various classes in the CSS package.
Version 1.4b18 of 22-Apr-2008
- Corrected a bug introduced into status reports in version 1.4b17.
That bug would cause the "Threads Total", "Threads Active", "Threads Inactive"
and "Threads Jammed" columns to display a range from
Integer.MAX_VALUEtoInteger.MIN_VALUEwhen no data was available. The correct behavior is to display "N/A" in such cases.
Version 1.4b17 of 21-Apr-2008
- When transmitting pages to clients,
IOExceptions, especiallySocketExceptions (usually reporting broken pipes caused by clients), are now handled by catching and logging them, rather than by catching, wrapping and re-throwing them. Depending on how a particular web application approaches its exception handling, this change can eliminate a cause of premature web application termination. - Disabled processing of Qwicap AJAX queries when Qwicap's AJAX support is disabled.
- Supplied the missing
Results.getDeclarationsmethod. - Classes that allow themselves to be enumerated now also implement the
Iterableinterface. Classes that implement theEnumerationinterface now also implement theIteratorinterface. - Upgraded the Table library from 1.0a32 to 1.0a36.
- Revised the
ServiceDataRecorderclass to populate the service data report tables with raw data (instead ofStringobjects) which is automatically formatted usingCellFormatters. This lays the groundwork for making the contents of Qwicap's status reports available programmatically. - Minor improvements to the Javadocs.
- The Ant build script for Qwicap, "build.xml", has been made more generic.
- Added Eclipse project files.
Version 1.4b16 of 16-Mar-2008
- Corrected bugs in the file upload code.
- Removed the Apache Commons File Upload library's source code from the Qwicap source tree. Instead, the File Upload library is included as a JAR, version 1.2.1, in the "lib/dist" directory. Also, updated the associated Apache Commons I/O library JAR to version 1.4.
Version 1.4b15 of 3-Mar-2008
- Further fine-tuning of the log messages associated with thread pool destruction, including the addition of a final report of any daemon threads that have resisted Qwicap's effort to persuade them to exit.
- Modified the
QwicapAbandonmentException.rethrowIfThisPageWasAbandoned(Throwable)method such that it will rethrowQwicapSessionDeathExceptionandQwicapSessionWillNotDieError, in addition to the various "abandonment" exceptions that it has always rethrown (when appropriate).
Version 1.4b14 of 3-Mar-2008
- Added code to the
MutableMarkupclass to detect the insertion, into one body of markup, of another body of markup that includes an XML declaration. Because there should be only one XML declaration in an XML document, and because it must be the very first item in the document, inappropriately located XML declarations are now omitted from the insert process (in the most common cases). - Made incident logging more elegant in cases where the incident forces the termination of a session of an application.
- Modified the thread pool shutdown log message to correct plural-related grammar issues when there was only one thread in the pool.
- The thread pool shutdown logging code now differentiates between daemon
and non-daemon threads in its thread descriptions, and only logs the stack
traces for daemon threads when the logging level is
FINEor lower. - After a Qwicap application's thread pool is destroyed, all lingering threads in its thread group are now interrupted. Such threads would have been created by code other than Qwicap, so they aren't Qwicap's direct responsibility, but testing shows that even daemon threads can persist across application deployments and can therefore create memory leaks. That's bad, so the interrupt operation has been added in the hope of inducing any such threads to stop in a timely manner.
Version 1.4b13 of 27-Feb-2008
As specified by RFC 3236, web pages transmitted by Qwicap are now identified with the MIME type "application/xhtml+xml" by default. (They used to be identified as "text/html".) However, if present, the "<meta http-equiv='Content-Type' content='...'/>" tag in an XHTML document's "head" section will be used to set the document's MIME type when it is transmitted, thereby overriding the default XHTML MIME type of "application/xhtml+xml".
By using the "application/xhtml+xml" MIME type, browsers will actually interpret XHTML documents as XHTML. Without it, they interpret XHTML as the usual HTML "tag soup". See "Sending XHTML as text/html Considered Harmful" for a discussion of this subject.
NOTE: Including a "<meta http-equiv='Content-Type' content='...'/>" tag in the "head" section of an XHTML (or HTML) document is a good practice, whether or not you want to override the document's MIME type. The reason is that the value of "Content-Type" can (and should) include a character set specification (for example: "application/xhtml+xml; charset=UTF-8"), which web servers in general (though not Qwicap) usually omit from the value of the HTTP "Content-Type" header. That omission leads to ambiguity in the interpretation of documents, which is bad by itself, but has also been shown to lead to security problems (see "Specify the output encoding").
- Corrected a bug in session tear-down that prevented some browsers from
retrieving
Downloadablesin the final page of a web application. - Added logic that prevents the submission of obsolete data sets (sets associated with pages leftover in a browser's cache/history) from automatically creating a new session when there is no current, valid session. In some browsers, in some situations, viewing a cached page whose URL includes a data set (AKA URI attributes, parameters, or a query string) causes that data set to be re-submitted to the web application. Qwicap has never allowed bad/obsolete data sets to reach its client applications, but it has been in the habit of starting a new session whenever a web application is hit in the absence of an existing session. Now, an obsolete data set sent to a Qwicap web application in the absence of an existing session causes Qwicap to prompt the user to decide whether or not they want to start the web application again. The page used for the prompt is named "qwicap-restart.html" and is embedded in Qwicap's "edu.utexas.its.eis.tools.qwicap.servlet" package. The message on that page reads (subject to change without notice): "Really Start [Web Appplication Name]? If you want to begin using the web application '[Web Application Name]' again, click on the 'Start' button below. If not, please close this window, or navigate elsewhere." The page may be overridden in order to substitute a custom page. See "Overriding Qwicap's Built-In Pages" below.
- Added user-friendly reports for two abnormal application exit cases: (1)
when the web application exits due to an exception, and (2) when the web
application exits without invoking one of the
Qwicap.goodbyemethods. In the first case, the exception is logged, but, for security reasons, no description of it is included in the web interface. Instead, an "incident code" is displayed. The code consists of the date, and a random number. The incident code is also included in the log record for the exception, so the developer can easily match a user's problem report to a particular entry in a log file. The page that displays incident codes is "qwicap-crash.html" and its title and header both read: "The web application '[Web Application Name]' has unexpectedly quit". The page that appears when the application exits without invoking one of theQwicap.goodbyemethods is "qwicap-exit.html" and its title and header both read: "The web application '[Web Application Name]' has quit". Both pages are buit into Qwicap's "edu.utexas.its.eis.tools.qwicap.servlet" package. Either page may be overridden in order to substitute a custom page. See "Overriding Qwicap's Built-In Pages" below. - Overriding Qwicap's Built-In Pages – Qwicap's built-in web pages, "qwicap-restart.html", "qwicap-exit.html" and "qwicap-crash.html" (see above) are all stored as resources in the package "edu.utexas.its.eis.tools.qwicap.servlet". Each of those pages may be overridden by a web application, simply by including a page of the same name among the other pages of the web application. Qwicap will find them automatically, and use them instead of its built-in pages of the same name. Further, Qwicap will: (1) replace the contents of all "span" elements having a "class" attribute that includes the class name "web-app-name", with the name of the web application; (2) set the content of the page's "title" element to the text contained in its "h1" element; (3) set the value of the "action" attribute of all "form" elements to the URL received in the request that triggered the display of the "qwicap-restart.html" page; (4) set the HTTP content type of the connection that will transmit the page to the client to "text/html;charset=UTF-8". Also, the "qwicap-crash.html" page will: (A) have the contents of any "span" element of class "incident-code" replaced with the incident code string; and (B) have the stack trace of the exception that describes the crash replace the contents of any "span" tag of class "exception" that appears within any element of class "show-exception", if (and only if) "development" mode is enabled.
Changed the error reporting mechanism of the
Qwicap.reportExceptionmethod such that, by default, it only shows high-security, opaque error reports ("incident codes"), and it no longer includes the stack traces for exceptions as comments in web pages. This change prevents information leakage that might aid attackers, and is therefore a very important change.However, that new, high-security behavior of
Qwicap.reportExceptionis less convenient for developers than the previous behavior, which was to display the exception's message as the user-visible error message, and to include the exception's stack trace as a comment in the web page source.To balance these concerns, the old, low-security/high-convenience behavior can be restored by creating a "context-param" named "qwicap-development-mode" with a value of "true" in your web application's "web.xml" file. It is anticipated that, if enabled at all, development mode will be disabled before applications are made available to their users.
- Added the
Qwicap.reportProblemmethod as an additional means of easily reporting errors to users. It differs fromQwicap.reportExceptionin that it cannot be used to report exceptions directly (and it should be used to report them indirectly only with caution, due to potential information leakage issues). Because of that limitation, its behavior does not have to change visibly when Qwicap is operating in its default, high-security mode. Therefore,Qwicap.reportProblemshould only be used to report errors whose messages have been reviewed to ensure that they do not reveal any information about the web application, its internal state, its underlying data stores, or anything else, that could aid an attacker in any way. - Internationalized some error messages in the
Qwicapclass that had previously been overlooked in the internationalization work. - Added to the Qwicap class the methods:
getBigDecimals,getBigIntegers,getDoubles,getLongs,getFloats, andgetInts. These new methods parallel the functionality of the pre-existing singular forms of those methods, but for controls with multiple values. - Added variants of the methods
toWWWFormURLEncodedStringandtoWWWFormURLEncodedBytesto theFormDataSetclass. These variants accept aURLAttributeSeparatorparameter. According to the relevant standards (RFC 1866, section 8.2.1, and the HTML 4 specification), the separator character can be either '&' or ';'. The semicolon character has the obvious benefit of not requiring encoding when placed in an HTML document. Ordinarily, this would be reason enough to always use the semicolon character, instead of the ampersand character, but—believe it or not—some web servers and/or CGIs don't support the relevant standards, and therefore don't recognize semicolons as URI attribute separators. So, when creating encoded data sets using theFormDataSetclass, you may now specify whether to use '&' or ';' as your attribute separator. Qwicap understands both. Other systems may not. - This version also attempts to provide a more consistent naming of methods
in the
FormDataSetclass (but doesn't necessarily succeed). - Reduced the
QwicapApplicationServicesclass to package-level access. - Extended the XML engine to support manipulation of CDATA, comments and declarations.
- The internal
CharacterSetFamilyUTF16class has been modified such that leading byte sequences that match UTF byte-order-marks (BOMs) are not removed from input data when further analysis of the data reveals that the input cannot be using one of the UTF-16 character encodings. - Gracefully handles the absence of certain basic character sets, like the EBCDIC family of character sets, which, evidently, are present in some Java distributions, but not others.
- Handles a
NoClassDefFoundErrorwhen using Qwicap's XML engine outside of a servlet environment. - Added some tests to
ResultsJUnit, and tweaked theResults.getBigIntegermethod. - Created the
QwicapBlockingListenerStatesclass to remove clutter from theQwicap.synchronizemethod by removing all of the code associated with notifying blocking listeners of blocking, holding their state while blocked, and then notifying the listeners when we unblock, returning their state to them when they are invoked. - Modified the
Form.actionRefersToThisWebAppmethod, and related code, to recognize the fact that "form" elements without "action" attributes nonetheless do submit their data sets to the current web application. - Modified the
Formclass to interpret lists of character sets in a form's "accept-charset" attribute. - Provided a much better implementation of the code responsible for adding the various "qwicap-" URI attributes to the URLs in a page, and, for the first time, it can also remove those URI attributes from the URLs in a page.
- Improved Qwicap's experimental AJAX features for visually reflecting the state of cached pages. The visual dimming effect used on pages that are no longer valid targets for user interaction is now clearer, cleaner and simpler. Also, the script now works in Safari and Firefox. Previously, it only worked correctly in Firefox. Internet Explorer compatibility is currently unknown. (These features, being experimental, remain disabled by default.)
- When the experimental AJAX features are enabled, and the user employs their browser's "back" button to return to an invalid page, they are presented with a dialog box informing them of the problem. That is not new. This is: If there is more than one valid page available from the web application at that time, they are presented with a pop-up menu of the valid page titles. Picking one takes the user directly to that page.
- Added code to prevent any scripts in the "onload" and "onunload" attributes of a page's "body" element from replacing Qwicap's own "onload" and "onunload" event handlers.
- Added encoding of single quote characters in URLs in order to prevent Javascript syntax corruption.
- Refactored all AJAX-related Java code into the
QwicapAJAXclass for neatness. - Added each web application's context path to many of the log messages that Qwicap produces in order to avoid confusion amongst log messages from multiple web applications on the same server.
- Eliminated a case in which a thread's session could be torn-down without freeing-up the thread for either future use, or garbage collection (depending on the thread pool settings).
In Tomcat versions 6.0.14 and 6.0.16 (and possibly many others), it has been observed that the re-deployment of a web application (but, oddly enough, not the shutdown of the Tomcat server) can trigger
NoClassDefFoundErrors during execution of the servlet'sdestroymethod. This appears to apply only to those classes that have not been loaded prior to the execution ofdestroy, but which are used by thedestroycode (directly or indirectly), and implies that the web application's class loader has been instructed to suspend class loading prior to the invocation ofdestroy.A means to change this behavior of the web application's class loader has not been identified. One workaround, however, is to force loading of the problematic classes before
destroyis invoked. TheQwicapServlet.initmethod, through use of the newClassPreloaderAndHolderclass, now performs such loading for several internal packages on which thedestroyimplementation depends, directly or indirectly. References to the loaded classes are retained by the servlet in order to ensure that they cannot be garbage-collected prior to servlet destruction.- When the
QwicapServlet.destroymethod is invoked, a more persistent thread shutdown algorithm is now employed, and, if all threads haven't shutdown after 30 seconds, the stack traces of the survivors are logged to aid in debugging. Also, warnings about applications exiting without invoking theQwicap.goodbyemethod are not shown when an application's thread was forcibly shutdown. - Corrected a problem in the thread pool implementation that left it unable to destroy a pool containing one or more threads that had not yet been started.
- Added a new last-ditch method for forcing a session to die, which is activated after a session has ignored a large number of coventional attempts to tell it to exit.
- Greatly increased the amount of information logged about "jammed" threads (assuming that such things still exist) by adding thread state and stack traces to the relevant log messages.
- To further ensure that the servlet destruction process is fully
understood, an instance-level concurrent execution counter has been
added to
QwicapServlet. The counter's value is logged when theQwicapServlet.destroymethod is entered, and again when it exits. If the counter is non-zero at exit, that would require some explaining. - Added a log message (level "INFO") announcing the invocation of the
QwicapServlet.destroymethod. (There was already a similar log message announcing the completion of thedestroymethod.) - Added to
QwicapThreadPool.destroya final check of the pool's thread group for active threads. It shouldn't be possible for there to be any at the point when this new code executes, but, if there were such threads, they would be worth knowing about. - Added more information to the log messages in the
QwicapThreadPool.destroymethod, including a tally of the states of all threads, in order to ensure that the pool shutdown process is fully understood. - Added a method to
QwicapThreadListto create a tally of the states of all threads in the list. - Removes a very small race condition in setting the "pool closed" flag during thread pool shutdown. It does not appear to have had any potential for negatively affecting the shutdown process. Nonetheless, the code is better-off without it.
- Improved comments in
QwicapThreadList, and eliminated some methods that are no longer used. - Revised the "build.xml" file such that it includes ".svn" directories in the project source zip file.
- Modified "build.xml" to automatically set the value of the
kQwicapVersionStrvariable in the "Qwicap.java" source file. As a result, the version number only has to be updated in one place, and the version string automatically includes a unique build number. - The "build.xml" file now provides a build step named "jar-without-libs" that builds a Qwicap JAR that does not include the various libraries in the project's "lib/dist" subdirectory. Qwicap still requires the presence of those libraries, so they'll have to be included in any project that uses Qwicap, but this library-free build of the Qwicap JAR makes it easier to avoid situations in which several libraries used in a project contain copies of the same library.
- Updated the internal "table" library.
- Javadoc additions and improvements.
Version 1.4b12 of 20-Nov-2007
- Re-enabled the
Qwicap.getStatusReport(boolean)method that had been disabled in version 1.4b11. However, the method had to be made an instance method, rather than a static method, due to the refactorings in version 1.4b11 that made it possible for Qwicap to maintain separate status information for multiple web applications when it is deployed as a shared library. - Added the static
Qwicap.getStatusReport(Class, boolean)method, so that a means remains by which status information can be obtained from Qwicap in contexts where no instance ofQwicapis available. The caller is required to pass in a reference to the class containing the web application's entry point (the "public static void main(String[])" method that Qwicap invokes to begin execution of the web application). The reference to the entry point class is required in order to determine which application's status should be returned. (In cases where Qwicap is deployed as a shared library, it may be maintaining status information for any number of web applications.) - Corrected a bug in the internationalization services discovery methods of
the
ResultsandMutableMarkupclasses. The bug could result in an exception being thrown, in some cases, when those classes were used outside of the context of a Qwicap web application. - The "Table" library, which is used internally by Qwicap to produce its status reports and many of its most informative logging messages, has been updated to the latest version.
Version 1.4b11 of 12-Nov-2007
- Adopted many Java 1.5-isms both internally, and in the public API.
- Qwicap can now operate within the default constraints of the Security Manager under Tomcat.
- Qwicap web applications can now run directly from their WAR files.
- Qwicap web applications that have traditionally only run in "unpacked" form, and have implicitly used direct file I/O to access their contents, can now run directly from their WAR files, without modification to their code.
- Major refactorings have been performed on
QwicapServletand the objects it creates and stores. The life-cycles of all of the static objects that were shared amongst servlets within the same class loader (with the exception of the random number generator) have been changed such that they are no longer shared. Instead, they are now specific to an instance ofQwicapServlet. Most notably, this means that thread pools are now servlet-specific, even when Qwicap is executed as a shared library. - The HTTP headers sent with all output have been adjusted to permit
client-side caching wherever possible. This reduces the number of requests not
only for static content in a web application, but for dynamically generated
Downloadableinstances. - The old
XMLCachehas been replaced by a general purpose document cache. TheXMLCacheclass remains in the library for the purpose of backward compatibility, but is now deprecated, and is omitted from the Javadocs. - Initial, and worst-case, sizes for the document and name caches are now programmatically determined based on an examination of the contents of each web application.
Qwicap.getDocument(String)will attempt to retrieve the specified document as a servlet container resource if the document name begins with a slash ('/') character. If the document name does not begin with a slash, an attempt is made to read it as a file. If that fails, a slash is added to the beginning of the name, and an attempt is made to retrieve it as a servlet container resource. (The outcome of this retrieval strategy is cached, so that future attempts to access the specified document will not have to repeat the aforementioned logic.)-
All invocations of the
Qwicap.getDocumentmethod, and all document requests made using the HTTP "GET" command, now automatically attempt to locate a version of the document that has been translated/localized in accordance with each user's localization preferences, as expressed in the HTTP "Accept-Language" header of their first request to the web application.Translated/localized versions of documents are expected to be stored in top-level directories within the web application. Those directories must be named after the language range from the "Accept-Language" header to which their translation/localization corresponds. In other words, if the "Accept-Language" header says that the user wants content localized for "en-gb", the appropriately localized versions of the web application's documents should be stored in a top-level directory named "en-gb" (lower case, with a hyphen separator).
Not all of the documents that make-up a web application require translation and/or localization. Therefore, Qwicap implements a search scheme that allows only the documents that require translation/localization to be duplicated, while others remain common to all languages/nations.
So, if a document named "mydoc.html" is requested directly by, or on behalf of, of a client whose preferred language is "en-gb", an attempt is made to retrieve the document "/en-gb/mydoc.html", then "/en/mydoc.html". If those attempts fail, the document search begins again in the directory containing the web application's default translation. If the default translation is "es-mx" (Mexican Spanish), the directory containing that translation will be named "es-mx (default)". (The postfix " (default)" marks a directory as the default translation.) Thus, the continuation of the search for the document "mydoc.html" would be: "/es-mx (default)/mydoc.html", "/es/mydoc.html", and, finally, "/mydoc.html".
The results of the search for each document translation/localization are cached, so the search is performed only once per document, per session of a web application. (Behind the session-specific search cache is an application-wide document cache, which not only caches documents that are found to exist, but caches the fact that other documents do not exist. This reduces the overhead of the searches that must be performed to populate the search caches.)
- Various user-visible items of text (input error messages, for example) that
were previously hard-coded into the various Qwicap classes are now stored in an
XML "properties" file. (The file is "Qwicap.properties.xml", which is built into
the Qwicap library as a resource in the "edu.utexas.its.eis.tools.qwicap.servlet"
package.) Web applications can override some, or all, of the values of items in
that file by providing a file of the same name in the same package. They can also
provide alternate translations, which will be used when they are appropriate to a
client's language preferences. (The same naming hierarchy scheme described for
ResourceBundle.getBundleis used, except that the extension of the files is ".properties.xml", instead of ".properties".) Web applications can also use this mechanism to isolate text in their own classes that will require translation/localization. They can access that isolated material by using the new methodQwicap.geti18nServicesForClass. - Added specific error messages for more input errors, and improved the text of many existing messages.
- Floating-point precision issues have been eliminated from the
Qwicap.getFloatandQwicap.getDoublemethods. - Integer magnitude issues have been eliminated from the
Qwicap.getIntandQwicap.getLongmethods. - Corrected an old bug in the
FormInputRejectionHelperclass that caused it to give-up too soon when searching the "form" elements in a page for a matching control. - Locale-specific decimal and grouping separators (for example "1,000,012.59" and "1.000.012,59", depending on your locale) are now acceptable in numeric input, and are used in error messages relating to that input.
- The
MutableMarkupclass has been modified such that it automatically recognizes the availability, or absence, of locale-specific services from Qwicap. In the former case, when insertingjava.util.Date,java.sql.Date,java.sql.Time, orCalendarobjects, string conversion is handled by formatters specific to the session's locale. In the latter case, things behave just as they always have - thetoStringmethod is invoked on the object, and whatever it returns is inserted into the markup. - The methods of the
Resultsclass that retrieve numbers from markup have been modified to use locale-specific services, when available, to parse those numbers. - Automatic character-set-awareness, including lie detection, is implemented for all inputs. Input may be encoded using ASCII-based character sets, EBCDIC-based character sets, UTF-8, UTF-16 (good luck finding a web browser that can construct UTF-16 input correctly, however), and any future character sets that Java elects to support.
- Corrected a failure to properly use Unicode byte-order-mark (BOM) information when examining markup.
- The
Context.getExistingResource(String)method has been added to simplify getting URLs for servlet container resources. It is based onjavax.servlet.ServletContext.getResource(String), but indicates that the requested resource is unavailable by throwing aFileNotFoundException, rather than by returning anullURL asServletContext.getResourcedoes. - Added user input de-bouncing. The problem typically arises from users accidentally clicking on a form's "submit" button more than once. Qwicap has never allowed such redundant input to reach its client applications, but it has been in the habit of showing a page navigation error message in response to redundant input, which has tended to confuse or annoy users. Redundant input is now specifically detected and silently discarded, so users get the outcomes they expect, without any indication that they accidentally submitted their input more than once.
- Automatic application URL clean-up. When POST requests whose URLs include query strings (suitable only to GET requests) are received, the browser is redirected to the "clean" version of the web application's URL, and processing of the original POST request proceeds normally, so the clean-up is transparent to the user.
- Using semicolons as synonyms for ampersands in the search portion of URLs, as suggested in RFC 1866, section 8.2.1, is now supported.
- Corrected a race condition in the tear-down of session context related to
the nulling of the reference to the associated
QwicapThreadinstance. - The rules associated with the "prompt pattern" have been relaxed in order to
allow more than one
promptinvocation within a particular implementation of the pattern. This is relevant, for example, when you want the prompt to include the previously submitted form data set in the page sent to the client in some cases, but not others, and therefore you need two different forms of thepromptinvocation (one for each case) within the same "prompt pattern" implementation. - The implementation of the
Downloadableclass has been improved. However, due to those improvements,Downloadableobjects are no longer instantiated directly. Instead, they are created by invoking the newQwicap.createDownloadablemethod. - The range of the random values that are incorporated into the URIs of
Downloadleinstances has been doubled to further ensure the uniqueness (statistically speaking) of those URIs. Also, those random values are now expressed in hexadecimal in order to reduce the length of the URIs. - The various, internal LRU caches now provide "discard" counters to track the number of items that have been removed from the caches.
- Many improvements to logging, primarily within the package "edu.utexas.its.eis.tools.qwicap.servlet". Setting the logging level to "FINE" will now provide extensive information about each hit.
- Removed a number of classes from the Javadocs that are not part of Qwicap's public API.
- Various Javadoc improvements.
Version 1.4b10 of 15-Jun-2007
- Resolves bugs in, and expands the functionality of, automatic character set detection.
- Corrects a bug associated with the new feature of
Auth2Schemeimplementations that allows them to force the destruction of a user's session. - Greatly increases the amount of information logged by the
QwicapServletclass, primarily at theFINESTlevel.
Version 1.4b9 of 31-May-2007
- The portions of Qwicap responsible for the reading and writing of XML and XHTML have been made character-set aware.
Version 1.4b8 of 22-May-2007
- Exception messages in the
MutableMarkupclass have been improved.
Version 1.4b7 of 17-May-2007
- The
Qwicap.reportExceptionmethod now logs the exception that is being reported (at the "WARNING" level). Previously, there was no logging in that method. The addition of logging greatly aids debugging when the exception being thrown is preventing the web application from reaching aQwicap.promptinvocation, and therefore is preventing Qwicap from ever reporting the exception.
Version 1.4b6 of 24-Apr-2007
- Corrected a bug in the
Hexadecimal.andASCIIFromBytesmethods (which are not a part of the public API, nor are they used by Qwicap) which could cause theOutOfMemoryErrorto be thrown due to a dramatic overestimation of the amount memory needed for the output buffer. The source of the problem was an operator precedence bug. This bug has no impact on Qwicap, but deserved to be fixed. - Changed the XHTML markup in the example applications such that the "meta" tags that specify "Content-Type" no longer include quotes around the "charset" value. Those quotes were causing Eclipse to choke.
- Changed the XHTML markup in the "guess" example application such that it is compliant with the XHTML 1.0 "Strict" specification, rather than the "Transitional" specification.
Version 1.4b5 of 18-Apr-2007
- Eliminated a case in
QwicapServletin whichHttpServletResponse.sendErrorwould throw anIllegalArgumentException, because anAuth2Schemeimplementation had refused access to the web application, and had already caused the response to be committed.QwicapServletnow invokessendErroronly when the response has not been committed.
Version 1.4b4 of 11-Apr-2007
- Corrected a stupid bug that prevented Qwicap's
SecureRandomservice provider from being accessed. Also corrected the associated Javadoc.
Version 1.4b3 of 10-Apr-2007
- Corrected a bug, introduced in version 1.4b2, that could cause a
NullPointerExceptionwhen rejecting the input from some form controls. JUnit tests have been added to ensure that this bug will not be re-introduced. - If the application server's security manager permits it, Qwicap's
"Rule 30" pseudo-random number generator (PRNG) implementation is made
available through the "Provider" mechanism of the
java.security.Securityclass. Thus, aSecureRandominstance which utilizes Qwicap's PRNG implementation, and which, by default, is seeded from Qwicap's internal instance of this PRNG, may be obtained by using the following invocation:SecureRandom.getInstance("Rule30", "Qwicap");. Note that this particular "rule 30" PRNG implementation has not been subjected to FIPS 140-2 compliance testing, though it has been subjected to similar tests, and other "rule 30" PRNG implementations appear to have satisfied FIPS 140-2 requirements.
Version 1.4b2 of 30-Mar-2007
- Upgraded the Jakarta Commons File Upload library from version 1.1.1 to 1.2, and the I/O library from 1.2 to 1.3.1.
- The
Hexadecimalutility class has been extended to support reading and writing of floating-point primitives, and the production of combined hexadecimal and ASCII representations ofbytearrays. The documentation has also been improved. QwicapServletnow overrides thetoStringmethod to provide an informative string.- The
CharactersandImRangeclasses now implement Java'sCharSequenceinterface.ImRangeis not part of Qwicap's public API, but this has implications for the public API: All pieces of immutable markup (tags, the whitespace outside of tags, individual attributes—everything) now support theCharSequenceinterface. If, for some reason, you want to take advantage of this fact, you'll have to determine that any givenRangeis immutable, by determining that it does not implement theMutableinterface. Then you'll have to typecast it toCharSequence. However, you can reliably assume that allRangeobjects in any instance ofImmutableMarkup(or any of its subclasses) are immutable without testing. - Added some defensive, and possibly unnecessary (but harmless), exception
handling to the
QwicapThreadPool.destroyAll,QwicapThreadPool.destroyOnly,QwicapThread.killThreadandQwicapServlet.destroymethods in order to ensure that servlet destruction is never interrupted. - Removed the
Qwicap.setInputFilter(FormDataSetFilter, boolean)method, which was created during the 1.4b2 development cycle, and added theQwicap.invokeInputFiltermethod as a much more elegant and readable means of dealing with the same problem. Also refined the handling of the data set that is on-hand whensetInputFilteris invoked. - After an invocation of
FormDataSetFilter, the data set (if any) that was sent with the current hit is filtered the next time an invocation of apromptmethod, or theredirectmethod, occurs, unlessinvokeInputFilteris used before then. - If, in the process of executing the actions specified by a
FormDataSetFilterResponse, aQwicapSessionDeathExceptionwas thrown, that exception would be caught and logged, rather than being allowed to propagate correctly. That has been fixed. - Deprecated the
Qwicap.rejectInput(String, Object, boolean, Object)method which, having been renamed fromrejectParameterlong ago, is a kludge leftover from the earliest days of Qwicap, before the distinction between strings and markup became apparent to me, and was properly embraced by the code. - Removed antique, deprecated "Parameter" methods from several classes,
notably the
Qwicap.rejectParametermethod. - Removed the
Qwicap.prompt(MutableMarkup, PromptFlags)method from the public API. It was a first attempt at solving a problem early in the version 1.4 development cycle, and has subsequently been solved more elegantly by theQwicap.prompt()method. Similarly, thePromptFlagsclass has been removed from the public API. - Added two methods to the
FormDataSetFilterResponseclass:clearandgoBackToFirstPage. - The
Form.addChoicemethod now throws anIllegalArgumentExceptionif the form does not contain a control of the specified name. - The
filtermethods of classes implementing theFormDataSetFilterinterface are now permitted to throwQwicapException. In fact, when they encounter such an exception, they are required to do so, because discarding such exceptions may prevent Qwicap from operating correctly. - The documents "Qwicap Introduction" and
"Comparison of Number Guess Implementations" have
been updated to use the new
Qwicap.promptmethod. Also updated both to assume that Java 1.5 is present, and therefore manual boxing of primitives is no longer required. (Qwicap itself continues to depend only on Java 1.4 features, however.) - The
Qwicap.prompt()method has been added, along with thePromptModifiersclass upon which it depends. This new method provides a much cleaner, and more readable, method of regulating the behavior of "prompt" operations than theQwicap.prompt(MutableMarkup, PromptFlags)method, which was created earlier in the version 1.4 development cycle. - Added the
Qwicap.showPageconvenience method for displaying non-interactive web pages whose input your code would ignore anyway. This is an alternative to thepromptmethod, and saves you the trouble of implementing the associated "prompt pattern". - Added
QwicapSessionAbandonedException, a non-public subclass of the publicQwicapAbandonmentExceptionclass, which is thrown when Qwicap detects that theQwicapSessionDeathExceptions it has been throwing, in an attempt to force the current session of a web application to shutdown, have been caught and thereby prevented from doing their jobs. Because of the Qwicap "prompt" pattern, this new exception is very likely to get through even in such cases. Unfortunately, without changing the "throws" declarations of a number of existing, publicQwicapmethods, this new exception can't be used everywhere thatQwicapSessionDeathExceptionis currently employed. - Added the
Null.orEmptyconvenience method. - Noticed that the documentation for
MutableMarkup.insertdoes not mention that it special-cases arrays andCollectionobjects such that "the contents will be interated through, with each element converted to a string, and commas inserted between elements. Whenever an element is found to be an array, or aCollection, the conversion process proceeds recursively, with the new material enclosed by brackets. (The elements ofbyteorBytearrays, will be displayed as unsigned decimal quantities. This seemed like it would be more useful to most developers than displaying signed quantities.)" This feature was documented in the Qwicap 1.2 change history, but it never made its way into the Javadocs. - Corrected a bug in
MutableMarkupthat could cause aNullPointerExceptionwhen inserting into the markup an array orCollectionthat includednullmembers. - The arrival of commands from Qwicap's experimental AJAX-style scripts no
longer causes the client application's (optional)
QwicapBlockingListenerto be invoked (twice) every time a command arrives. The client application should be oblivious to script command processing, so this is a useful change. - The
Qwicap.redirectmethod now acts on any input that arrives when the user returns to the web application from the redirect. This includes filtering the input, if aFormDataSetFilterhas been set. Previously,Qwicap.redirectignored input. - Added the convenience method
FormDataSet.notEmpty. - Fixed a significant bug in
Qwicap.addBlockingListenerand also improved it such that it will not add duplicate listener instances to its list. - Made public the constructors of the
FormDataSetclass. - Added the
FormDataSet.hasconvenience method. - Altered the
FormDataSetFilterinterface to simplify the parameters passed to thefiltermethod, and to include a new parameter of typeFormDataSetFilterContextwhich provides new information about the context in which the data set is being filtered. - Removed obsolete material from the
FormDataSetFilter.filterdocumentation. - It is now possible to use Qwicap in a shared library setup, for
example where Qwicap is installed in Tomcat's "shared/lib" directory,
instead of in each web application. To get around class loader
hierarchy problems, web applications intended to operate in such an
environment must subclass the
QwicapServletclass. See the documentation forQwicapServlet.init. - Found and corrected an ancient bug that caused "bad input" loops
if forms, or parameter-bearing links, were added to a page between an
invocation of
Qwicap.promptand the rejection of some of the input from that page. - Rejecting all input from a page no longer creates a log message at level "INFO". It now produces a log entry at level "FINE", just as rejecting a single input has done for some time.
- The service data recorder's hourly status reports are now logged at level "FINE", instead of "INFO".
Version 1.4b1 of 1-Mar-2007
- Filled-in some old gaps in the Javadoc, and made numerous improvements to the Javadoc markup throughout the classes of the public API.
- Added to the authentication & authorization (Auth2) system the ability to regulate access to the static content in a web application, independently of access to the application itself.
- Rearchitected the authentication & authorization
(Auth2) code.
The new implementation uses an
Auth2SchemeFactoryassociated with each servlet to produce anAuth2Schemeinstance (optionally associated with each session) which is used to authenticate & authorize each hit in a session. It returns to Qwicap anAuth2SchemeReplyinstance describing its conclusions, upon which Qwicap acts, restricting access to the web application and/or its static content accordingly. The client application may retrieve the current reply object by using the newQwicap.getAuth2SchemeReplymethod. (The oldQwicap.getAuth2Schememethod has been discontinued.) - Modified a number of core classes to reflect a better understanding
of servlet life cycles. This cleaned-up the code in a number of places,
and outright eliminated the need for the internal
QwicapContextclass. - Simplified the web application deployment descriptor (the "web.xml"
file) by eliminating the need to specify
edu.utexas.its.eis.tools.qwicap.servlet.QwicapContextas a "listener". Revised the Deployment Descriptor documentation accordingly. (Web applications using previous versions of Qwicap 1.4 will need to remove that "listener" specification from their "web.xml" files.) - Added several new methods to the
Resultsclass:getAttribute,everyNth, andIF_NOT_EMPTY.
Version 1.4b0 of 9-Feb-2007
- Corrected the handling of newline ('\n') characters within the content of HTML "textarea" tags. Previous versions of 1.4 had replaced those newlines with "br" tags, which was incorrect. Newlines in "textarea" tags are now left as they are; they are not encoded. In this respect, "pre" and "textarea" tags are now handled identically.
- Added a few more JUnit tests, and improved a few others.
- Added the
Qwicap.getRandommethod to make available to client applications Qwicap's internal pseduo-random number generator instance. - Updated the "guess" and "wumpus" example applications to use the
Qwicap.getRandommethod. Also, removed the "wumpus" application's dependence on the "servlet.jar" library file, and duly removed that file from the distribution. - Corrected a bug that may have caused Qwicap to interfere with normal Tomcat shutdown.
- It is no longer necessary to include the "qwicap.css" style sheet in Qwicap applications. Qwicap will now supply that document automatically. However, it remains necessary for an application's style sheet(s) to import the "qwicap.css" style sheet, unless it overrides all of Qwicap's styles. Applications may still override the default Qwicap styles in their own style sheets, of course, and may outright replace the default "qwicap.css" style sheet, if they prefer, by providing a document of the same name in the application's top-level directory.
- Various Javadoc improvements, chiefly in classes that are not part of Qwicap's public API.
- Corrected an error in a Javadoc block and in a separate comment
in the
QwicapServletclass. The word "send" in both cases had been transformed into "sendFile" due to some overzealous refactoring in the distant past. These corrections have no functional significance, but do make a little bit of the documentation more comprehensible.
Version 1.4a42 of 11-Dec-2006
- Tests indicate that the last, elusive race condition associated with interrupted hits (think of a user clicking on a submit button twice, before the first hit has been fully processed) has been removed.
- Revised the Qwicap Deployment Descriptors document for version 1.4a42.
The internal
ServiceDataRecorderclass now emits the data it has gathered via aLogger. It does this the first time something happens each hour (logged at theINFOlevel), and whenever the active session count drops to zero (logged atFINE). The same data can be obtained as aStringobject using the newQwicap.getStatusReportmethods. An API for programmatically accessing this highly changeable data has not yet been defined, because I am hesitant to commit to what data will be gathered, how it will be represented, etc. At the moment, no more than 72 hours of data, in one hour units, is retained (and reported) at any given time. Currently, the data is reported like this:+---------+---------+----------+-----------+---------+------------+-----------+----------+----------------+--------+------+------------------+---------------+------------------+----------+ | Pool | Threads | Threads | Threads | Threads | Threads | Sessions | Sessions | Session Length | Hits | Hits | Hit Runtime | RAM Free MB | RAM Used MB | RAM | | Size | Active | Inactive | Born/Died | Jammed | Unvailable | Completed | Expired | Min/Avg/Max s. | Total | Bad | Min/Avg/Max ms. | Min/Avg/Max | Min/Avg/Max | Total MB | +------------------+---------+---------+----------+-----------+---------+------------+-----------+----------+----------------+--------+------+------------------+---------------+------------------+----------+ | 2006-10-20 05 PM | 0-200 | 0-200 | 0-200 | 200/0 | 0 | 0 | 2,011 | 0 | 0.8/39.6/145.3 | 63,939 | 0 | 1.0/21.0/6,651.0 | 0.4/21.7/48.8 | 31.7/89.0/89.9 | 395.6 | | 2006-10-20 06 PM | 200-300 | 0-300 | 0-300 | 100/0 | 0 | 0 | 3,008 | 0 | 0.6/47.6/187.4 | 94,267 | 0 | 0.0/15.5/3,407.0 | 0.4/27.3/66.3 | 89.9/103.2/115.3 | 395.6 | +------------------+---------+---------+----------+-----------+---------+------------+-----------+----------+----------------+--------+------+------------------+---------------+------------------+----------+
- The size of the stack used by Qwicap's pooled threads can now be
configured in the web application deployment descriptor file ("web.xml").
A size of zero causes the platform's default thread stack size to be
used. Any other value is offered to the platform as a suggestion for
a thread's stack size. (That's just how the
Threadclass works; it's not up to me.) In general, I think setting the stack size is only appropriate as a server-specific deployment optimization, and web applications should ship with the stack size set to zero so that each platform's (presumably safe) default size will be used. HTMLEntityCodechas been simplified by eliminating support for the modes in which unprintable characters were omitted, or translated to hex.- Qwicap now gets all of its threads from a thread pool. The thread pool is configured in the web application deployment descriptor ("web.xml" file). The thread pool, and the individual threads, have been heavily instrumented to gather data about pool utilization, thread performance, memory usage, etc.
- The concept of "blocking listeners" has been added to Qwicap. Such
listeners, registered using the new
Qwicap.addBlockingListenermethod, are invoked just before and after Qwicap blocks to wait for user activity. This applies to thepromptmethods, and theredirectmethod, and will apply to any future blocking methods. Thus a "blocking listener" can perform actions like releasing and reacquiring limited resources like database connections, or log application activity, transparently from the perspective of a web application's code. - The code responsible for inserting strings into XHTML markup now examines the context into which the strings are being inserted. If they are inserted into pre tags, Qwicap 1.4's usual practice of encoding new-line characters as br tags is disabled.
Version 1.4a37 of 26-Jun-2006
- Deprecated all of the
Qwicap.prompt*methods except forQwicap.prompt(MutableMarkup). The functionality represented by the other variants of thepromptmethod is now supplied by theQwicap.prompt(MutableMarkup, PromptFlags)method. The newPromptFlagsclass is the means by which the various optional behaviors associated with prompting, and rejecting input, are configured. This change eliminates the growing variety ofpromptmethods, allows configuration that wasn't previously possible, and provides some future-proofing to the Qwicap API. - When the user clicked on a web page, then clicked on it again before
the page from the previous click had loaded, Qwicap was encountering an
error caused by it being too careful about checking errors when
writing pages to clients. So, Qwicap no longer invokes
checkErroron thePrintWriterobjects it uses to write pages to clients, and therefore is no longer bothered by the client-side of connections being closed prematurely. - Fixed a problem which could leave servlet threads waiting to interact with dead Qwicap threads.
- Removed the
mainmethod from theArrayToStringclass. It was leftover from testing.
Version 1.4a34 of 18-Jun-2006
- Reworked the servlet-specific session attribute naming code, and
introduced the
getSessionAttribute,setSessionAttribute, andremoveSessionAttributemethods to theContextclass. - When adding duplicate choices using
Form.addChoice, the pre-existing choices that are made redundant by the additions are removed from the form. - Provided a helpful error message when
Qwicap.getCurrentInstanceis invoked in a situation where there is no current instance ofQwicap. The automatic web application entry point discovery code, which searches all of a web application's classes for a "
public static void main(String[])" method to use as the application's initial entry point, was provokingNoClassDefFoundErrors when it examined classes that included references to missing classes. In some cases this was just revealing errors that were going to happen on their own in short order. In other cases, however, it was revealing errors that wouldn't have arisen, because the classes with unsatisfied links weren't going to be touched explicity, or implicity, by the web application. While it was simple enough to catch those errors, doing so sometimes seemed to leave the class loader, or some other part of the runtime environment, in an unstable state.In order to avoid those problems, Qwicap now has its own class file parser, so that it can examine classes without use of a class loader, or reflection. The parser also gives Qwicap the ability to examine the dependencies of the classes it is considering using as entry points, so that it can select a class which not only has a "
public static void main(String[])" method, but one that uses theedu.utexas.its.eis.tools.qwicap.servlet.Qwicapclass, as well. This should eliminate some cases where Qwicap couldn't narrow down the set of available entry points to a single, definitely-correct choice, and therefore had to give-up and throw an exception.- Fixed a concurrency-related bug in the context management code.
- Version 1.1.1 of the Jakarta Commons FileUpload library (less the portlet-oriented classes) has been incorporated into Qwicap, replacing version 1.0. (Also, because the new FileUpload library depends on it, the Commons IO library is included, though Qwicap, itself, doesn't make use of it.)
- Removed some logging that was leftover from previous testing and debugging work.
- One more way of confusing Qwicap by replacing sections of page markup
that contain active form elements has been eliminated, and
a
NullPointerExceptionalong with it. - Extended support, to all relevant control types, for multiple occurrences of single-value form controls with the same names in the same form.
- It is now much harder to confuse Qwicap by replacing the sections of
page markup that contain active form elements. If you do
find a way to confuse Qwicap in this manner, a
FormNotFoundExceptionis thrown with a message that will state the nature of the problem clearly. - The code for building comments in markup (currently used only to add strack traces to exception reports) is more conformant with the XML specification in that: (1) Sequences of two dashes ("--") are removed from comment text (they are replaced with "—" which describes the omitted material correctly, even though character entities aren't interpreted in comments). (2) Control characters other than 0x09, 0x0A and 0x0D are removed from comment text. (3) HTML entity encoding is no longer performed on comment text.
- Page navigation error reports are now removed from pages immediately after they are transmitted to a client for the first time. Consequently, the client sees any particular page navigation error report only once, even if they reload the page. This eliminates a behavior that could sometimes seem like nagging.
- Corrected a bug that resulted in the Unicode characters 0x201C and 0x201D being included in most Qwicap error messages, rather than the HTML entities that represent them ("“" and "”").
- Back-to-back input processing failures (obscure failures to load mutlipart form data sets) would result in multiple copies of the associated error message appearing in the page sent to the client. This has been fixed.
- Corrected a sign-extension related bug in
Hexadecimal.fromByte. - Attempts to reject a form control that does not actually exist in the current form now cause an exception to be thrown with an error message that specifically describes this problem. In the past, a more general error message was used, and it was too general to help developers identify this problem. The general error message, used in other cases, has also been made significantly more informative.
- Corrected a bug in reporting some obscure form input processing failures that prevented the relevant style in "qwicap.css" from applying to the error message inserted into the page.
- Improved the manner in which servlet threads and Qwicap threads synchronize.
Also, some unnecessary synchronization in the
Qwicapclass was eliminated. - Added the ability to specify a class that can pre-process all input
received from the client machine, before Qwicap acts on it, or passes it
along to the client application. See the
FormDataSetFilterinterface. - Added the
Qwicap.rejectInput(Object)method to allow all of the input from a "form" element to be non-specifically rejected. - Because we ran into the problem of
SecureRandomintermittently throwing ajava.security.ProviderExceptionwith the error message "Could not obtain session" when running under Solaris, and because it was a while before we realized there were patches to Solaris that correct that problem, Qwicap no longer uses theSecureRandomclass. Instead, Qwicap now has its own pseudo-random number generator (PRNG), inspired by Wolfram's use of the rule 30 cellular automaton as a random number generator in Mathematica. Now that we've gotten to the bottom of the Solaris bugs, Qwicap could resume use ofSecureRandom, but, according to Wolfram's analyses, the Rule 30 PRNG should be stronger than other PRNGs. Form.setDataSetwill no longer try to embed values in "input" controls of type "submit".- Added the
Match.hasAttributeOfValuemethod. - Added the
Qwicap.goodbye(String)method, which accepts a URL as a string, and redirects the client to that page while shutting down the Qwicap application. - Added the
Qwicap.redirectmethod, which redirects the client to an external web page (one that, typically, isn't part of the web application that's performing the redirect), and blocks until the client returns to this web application. Added the ability to control whether or not the
Qwicap.rejectInputmethod places quotes around the rejected control's label and value. By default, both are quoted. However, if you add the class "qwicap-no-quotes" to the element marked with the class "qwicap-label-text" in your error message markup, the label string will not be quoted. Similarly, if the class "qwicap-no-quotes" is added to the element marked with the class "qwicap-param-value", the value string will not be quoted.For example, your error message markup that once read as follows:
The input <span class='qwicap-param-value'></span> is not a valid value for the field <span class='qwicap-label-text'></span>. Please fix it.
...could be prevented from quoting the control label and value by changing it to the following:
The input <span class='qwicap-param-value qwicap-no-quotes'></span> is not a valid value for the field <span class='qwicap-label-text qwicap-no-quotes'></span>. Please fix it.- Added the
Match.hasClassmethod. - Made the Javadoc for the various flavors of
Qwicap.rejectInputmore consistent, and eliminated some typographical errors. - Eliminated the possibility of a
ClassCastExceptionin the methods that modify tag attributes when invoked on material other than start tags and empty tags. - Added the
Results.getBooleanmethod.
Version 1.4a12 of 22-Feb-2006
- Corrected a bug in
Results.ELSEand added JUnit tests for all combinations ofIF/ELSE/ENDIFinvocations, so there won't be any more bugs like it in the future. - Downloadables weren't being downloaded when their URIs included encoded characters, e.g. %20. This has been fixed.
- When a downloadable requested by a client could not be found, no error report was returned to the client. This has been fixed. The client will now receive an HTTP 404 error, and an explanatory message.
FormDataSet.printnow produces easier-to-read output, with control names and values arranged in columns. Also, the output is sorted by control name.- Javadoc improvements.
Version 1.4a10 of 7-Feb-2006
- Optimizations to the
MutableMarkupclass' internal list insertion code and related methods. - Corrected a set of namespace-related bugs in
MutableMarkupandImmutableMarkup. The fixes required that thesetNamespacemethod be removed from theNamedIteminterface, access to theImNamedItem.setNamespacemethod be reduced from public to "package", theImNamedItemclass be made "public" (it shouldn't be public, but it must be accessed across package boundaries, so there's no choice), and the addition of aclone(Namespace)method toImNamedItemin order to create copies of immutable markup elements in different namespaces than the originals (the new objects continue to share the same immutable backing store as the originals). MutableMarkup.clonenow produces a newMutableMarkupwhich cannot be affected by changes to the original object, and vice versa. The previouscloneimplementation only offered partial protection from such changes.- Optimizations added to the conversion of
MutableMarkuptoImmutableMarkup. - Removed the static member
HTMLfrom the public API ofMutableMarkup. It may still be used, however, through the newhtmlEncodeandhtmlDecodestatic methods. - Changed the configuration of the
HTMLEntityCodecobjects used byQwicapandMutableMarkupsuch that newline characters ('\n') are encoded as "<br/>", rather than being omitted, which has been the behavior until now. Note that this does NOT affect the manner in whichMutableMarkupencodes attribute values; newlines continue to be omitted from attribute values. - Removed the
Pageclass from the public API. It was never meant to be in the public API, but as long as theFormclass depended on it, it couldn't be hidden. That dependence has been eliminated, soPagewill never clutter the API documentation again. - The
Formclass no longer depends upon thePageclass. It works just as before, except that thesetFormDataSet()method is no longer available. (The methodssetFormDataSet(FormDataSet)andsetFormDataSet(HttpServletRequest)remain.) - Deprecated the
MutableMarkup.embedParametersandMutableMarkup.embedParametersIfPossiblemethods. They are replaced byMutableMarkup.embedFormDataSetandMutableMarkup.embedFormDataSetIfPossible, respectively. This brings the method names more in line with official W3C nomenclature. - Removed an old optimization from the page stack maintenance code, because I finally found a case where it produced undesirable results.
- Added the
Qwicap.printPageStackmethod as an aid to debugging and/or understanding Qwicap's page stack and the way in which it is automatically maintained. - Corrected a bug that arose while setting the value of an XML
attribute to
null. - Added
getBigIntegerandgetBigDecimalmethods to the classesQwicapandResults. - The
Form.setControlValuemethods now examine the value object to determine whether or not it is an array. If not, the methods behave as they always have. If so, and the specified control is a multi-value control, the control is given all of the values listed in the array. The array may be of any type. ThetoStringmethod will be invoked on each of its elements. - Extended the functionality of the
Formclass by adding (or exposing) static methods that represent all of the class' key functionality, but that operate on a single control identified by aMatchobject. This makes the functionality of theFormclass available in situations where you do not wish to operate on an entire form, or in which you are producing or modifying the markup for control elements outside of a "form" element. - Added a number of
enableControlsmethods to theFormclass to achieve symmetry with the existingdisableControlsmethods. - Finally implemented the full functionality originally intended
for the
Form.addToControlValuemethod. It used to handle adding values to the multi-value controls ("select" and checkboxes), and did reasonable things to radio buttons, but wasn't useful for much else. Now it will handle most other types of controls by appending the supplied value to the existing control values. An obscure operation, in my experience, but it allows the method to "do what it says" no matter what sort of control it encounters, and there's value in that sort of consistency. - Corrected recurring HTML syntax errors in the Javadoc for the
ResultsandFormclasses. - Added the convenience methods
addFirstChoiceandaddLastChoiceto theFormclass. These are the same as invoking the pre-existingaddChoicemethod with itsInsertBeforeparameter set totrueandfalse, respectively. - The method
Form.addChoiceused to assume that there was only one control (or group of controls, in the case of radio buttons and checkboxes) with the specified name in any given form. It has been updated to handle the case where there are several, and to add the new choice to each of them. Unfortunately, this only works with "select" controls, because radio buttons and checkboxes lack any enclosing element that would make it possible for groups to be individuated. - Corrected a bug in
ImmutableMarkup(MutableMarkup)that allowed namespace information to be lost when converting mutable elements into immutable elements. - Immutable documents created using
ImmutableMarkup(MutableMarkup)now inherit the names of the mutable documents from which they were created. - In order to maintain consistency with the
Resultsclass, the methodMatch.insert(boolean, Object)has been deprecated, and replaced withadd(boolean, Object). Work on method name consistency and readability in the
Resultsclass:Deprecated Replacement insert(boolean, Object)add(boolean, Object)insertBeforeaddBeforeinsertAfteraddAfteraddContentBeforeaddToStartOfContentaddContentAtStartaddToStartOfContentaddContentAfteraddToEndOfContentaddContentAtEndaddToEndOfContentadd(Match)addMatch(Match)add(Results)addResults(Results)addTo(Results)addToResults(Results)- Added
getFloat,getInt,getShort, andgetBytemethods to theResultsclass. - Added
cutandcopymethods to theResultsclass. - The methods
Results.extractandResults.extractToMarkupnow set the name of the new markup object they produce. The name will read Derivative of "Original Markup Name", where "Original Markup Name" is the name of the markup from which the new markup was extracted. This is identical to the behavior of thetoMarkupmethod, which has always behaved in this way. - Improved the error message in
MutableMatch.check, which was already one of the longest and most detailed in all of Qwicap. - The
FormControlValueclass now implements theComparableinterface, and provideshashCodeandequalsmethods. All of these methods operate on the name of the form control, and not the value. - Added the
get(Pattern),getValue(Pattern), andhasControlNamesMatching(Pattern)methods to theFormDataSetclass. Form.createChoicenow encodes the values of the attributes in the markup it produces. This also benefitsForm.addChoice, which usescreateChoice.FormDataSet.hasParameterNamesStartingWithhas been deprecated and replaced withFormDataSet.hasControlNamesStartingWith, which is more consistent with official W3C nomenclature.Match.printnow returns a reference to the instance ofMatchon which the method was invoked.- Eliminated more unused methods, and removed more constructors and methods from the public API.
- Corrected some omissions in the Javadoc class description for the
Qwicapclass.
Version 1.4a6 of 24-Jan-2006
- Added the
Qwicap.promptCompletemethod. This method allows a method that displays a page (by implementing the "prompt" pattern for it) to explicitly inform Qwicap when it has finished with the page. Qwicap then regards the page as dead, and knows to ignore input from cached copies of it. Frequently, it is isn't necessary to invoke this method, because Qwicap will automatically figure-out that a page is dead if its supporting method (the one that implemented the "prompt" pattern for it) has exited before the next invocation of one of the "prompt" methods. Nonetheless, there are situations where the automatic dead page detection is not sufficient, and this method will let you disambiguate those situations. Failure to use this method when it is necessary can lead to some sub-optimal page management, but won't lead to a crisis, so think of this method as a page navigation optimization, rather than a necessity. - Corrected a bug that sometimes allowed pages that were not "in play" to remain on the page stack, which permitted Qwicap to operate under the delusion that such pages actually were still "in play". An attempt by a user to go back to such a page would cause Qwicap to discard all pages on the stack, effectively terminating the application.
- Added support for "modal" pages. (Pages that represent a mode in
the application, and which therefore cannot be abandoned using a
browser's "back" button. This is directly analagous to modal dialogs
in GUIs, which demand that the user interact with them before the user
is once again allowed to interact with any other part of the application.)
Support for modal pages takes the form of a new "prompt" method, named
promptModalSynch, in theQwicapclass. It works exactly like the previouspromptmethods, but causes the page it displays to be treated in a modal manner. For consistency, thepromptModelessSynchmethod has been added so that applications can make explicit their choice to use modeless pages. The existingpromptmethods remain, and are considered synonymous withpromptModelessSynch. - Page navigation errors are now explained to the user. Attempts to go back to pages that are no longer "in play" (their implementing method is no longer in the call chain), and attempts to go back to pages that precede a modal page, cause explanatory error messages to be displayed. Previous versions correctly diagnosed and responded to navigation errors, but did not explain the situation to the user, which could cause confusion. In order for these errors to be displayed correctly, applications must replace their old copies of the "qwicap.css" style sheet with the new one supplied in this release.
- Removed unused methods from several classes.
- Removed unnecessary synchronization on the
Qwicap.promptmethods. - The constructors in the
QwicapAbandonmentExceptionclass have been removed from Qwicap's public API, and an unused constructor has been removed entirely. - The constructor for the
QwicapSessionDeathExceptionclass have been removed from Qwicap's public API. - More methods in the
Pageclass have been hidden. Updated the Javadocs to explain thatPageis not part of Qwicap's public API.
Version 1.4a4 of 8-Jan-2006
- Various improvements to the Javadocs.
- Added the
Qwicap.getFloatmethod, for retrievingfloatprimitives from user input. This is slightly preferable to the past practice of usinggetDoubleand typecasting the result tofloat. - The
Downloadableclass has been exposed in the public API, because it is a convenient wrapper for the information triplet representing any downloadable item (name, MIME type, and content bytes). Note thatDownloadable.toStringreturns the unique URI assigned to the downloadable, which means that aDownloadablecan be passed directly toResults.setAttribute, when creating the link to the downloadable. - The various attribute manipulation methods in the
Resultsclass (and all of the lower-level classes on which it builds) now accept arbitrary objects as the values of attributes. The ultimate value of an attribute is whatever the specified object'stoStringmethod returns. If the specified object is actuallynull, the value of the attribute is empty, e.g. "... myattr='' ...". QwicapSessionDeathExceptions now come with messages specifying the reason the session died, or is dying.- The
Qwicap.goodbyemethod now initiates the shutdown of Qwicap and its client application. Previously, it was up to the the client application to shutdown in a graceful manner. This new behavior should force applications to do the right thing, by depriving them of the use of allQwicapmethods for prompting, retrieving input, etc. - Removed some unnecessary, old code from the
Qwicapclass. - Eliminated a race condition that could occur as a Qwicap application exits.
- Many more revisions to the "Hunt The Wumpus" demonstration application. Bugs in the game have been removed, features have been added, and, more significantly, a configuration page has been added which demonstrates more Qwicap functionality.
Version 1.4a0 of 1-Jan-2006
- Dramatically revised the "Hunt The Wumpus" demonstration web application. It now presents the cave map graphically—including such state information as your present location, and which rooms you've visited in the past—using dynamically generated JPEGs. Users indicate their moves by clicking on the map image which is dynamically marked-up as a client-side image map. Shooting arrows is now a single-click operation. These changes make game play dramatically faster and easier - almost too easy, but that's the virtue of a good interface.
- Changed the algorithm for producing the URIs of downloadables, in order to work-around the problems created by Internet Explorer for Mac (and, one assumes, Windows) being unable to recognize and/or comprehend HTTP cache-control directives.
- Improved the documentation for
Qwicap.convertSubmitButtonsToInputs, which is a work-around for the hideous bugs in the "button" element handling code of Internet Explorer (Mac and Windows). - Improved the error messages produced by the XML tag hierarchy validation code such that all of them specify the name of the document in which the error was found, provided that the XML came from a document with a known name.
- Added support for links that supply parameters ("a href" and "area href", so far). Previously, Qwicap only accepted parameters from controls in forms. [Dear W3C, Can a set of parameters be called a "form data set" when they don't originate from a form?]
- Removed the constructor of the
Contextclass from the public API. Also removed from the public API the following methods:go,getSessionContextCount, andclose. Client code has no need for those. - Removed the method
Context.getfrom the public API. Client code that wants access to the currentContextobject has always been able to get it usingQwicap.getContext. - Documented the
Context.getFileandContext.getExistingFilemethods. - Deprecated the
Results.addContentBeforeandResults.addContentAftermethods, in favor of the newResults.addContentToStartandResults.addContentToEndmethods, respectively. The new methods accept exactly the same parameters as the methods they replace, the only differences are the (hopefully) more comprehensible names. - All subclasses of
Markupnow havegetMutableandgetImmutablemethods. If a markup object is already in the requested state, the methods do nothing, and return a reference to that object. If the markup object is in the opposite state, a copy is created in the requested state, and that is returned. - Added support for dynamically-generated downloadable files. Just
produce the contents of the "file" as an array of bytes and give them to the
new
Qwicap.addDownloadablemethod. That method will return a unique URI for the downloadable, which you then use as the value of an "a" tag's "href" attribute, an "img" tag's "src" attribute, or an "object" tag's "data" attribute. The downloadable is automatically associated with the next page sent to the client. When that page ceases to be "in play", the downloadable automatically becomes available for garbage collection. - As a result of the previous two changes, most Qwicap applications can now use a generic "WEB-INF/web.xml" file (as seen in the examples, and documented in the "Qwicap Deployment Descriptors" document), thereby reducing the number of possible deployment problems, and the number of things a developer has to learn in order to use Qwicap.
- Qwicap can now discover its client class in any given web application
by performing a run-time examination of the application classes, be they a
hierarchy of separate class files in "WEB-INF/classes", or just a flat group of
JAR files in "WEB-INF/lib". Specifically, Qwicap looks for a class containing a
"
public static void main(String[])" method. Provided it finds only one such class, Qwicap will automatically use that method as the web application's starting point. If your web application has more than one class containing such a method, you will have to continue setting the "QwicapClientClassName" initialization parameter in your "WEB-INF/web.xml" file. - Simplified web application setup where it concerns the "url-pattern" in the "servlet-mapping" element of the "WEB-INF/web.xml" file. Now, any application can simply set the value of "url-pattern" to "/". Ordinarily, that would prevent HTTP GET requests for the application's CSS documents, and any other static documents, from operating correctly (they'd invoke the servlet, rather than cause the requested documents to be returned). Now, Qwicap disambiguates the request itself, and, if necessary, handles the transmission of the requested document to the client. As a result, the URLs that are used to access web applications can be made simpler and more natural. For example, the URL for the Qwicap number guessing game example, a web application named "guess", can be reduced from "http://localhost:8080/guess/app" to "http://localhost:8080/guess".
Version 1.3.3 of 8-Jan-2006
All of the following changes were back-ported from Qwicap 1.4a4 in order to correct bugs, or to make simple enhancements.
- Eliminated a race condition that could occur as a Qwicap application exits.
- The
Qwicap.goodbyemethod now initiates the shutdown of Qwicap and its client application. Previously, it was up to the the client application to shutdown in a graceful manner. This new behavior should force applications to do the right thing, by depriving them of the use of allQwicapmethods for prompting, retrieving input, etc. - Added the
Qwicap.getFloatmethod, for retrievingfloatprimitives from user input. This is slightly preferable to the past practice of usinggetDoubleand typecasting the result tofloat. - The various attribute manipulation methods in the
Resultsclass (and all of the lower-level classes on which it builds) now accept arbitrary objects as the values of attributes. The ultimate value of an attribute is whatever the specified object'stoStringmethod returns. If the specified object is actuallynull, the value of the attribute is empty, e.g. "... myattr='' ...". QwicapSessionDeathExceptions now come with messages specifying the reason the session died, or is dying.- Improved the documentation for
Qwicap.convertSubmitButtonsToInputs, which is a work-around for the hideous bugs in the "button" element handling code of Internet Explorer (Mac and Windows). - Removed the constructor of the
Contextclass from the public API. Also removed from the public API the following methods:go,getSessionContextCount, andclose. Client code has no need for those. - Removed the method
Context.getfrom the public API. Client code that wants access to the currentContextobject has always been able to get it usingQwicap.getContext. - Improved the error messages produced by the XML tag hierarchy validation code such that all of them specify the name of the document in which the error was found, provided that the XML came from a document with a known name.
- All subclasses of
Markupnow havegetMutableandgetImmutablemethods. If a markup object is already in the requested state, the methods do nothing, and return a reference to that object. If the markup object is in the opposite state, a copy is created in the requested state, and that is returned. - Documented the
Context.getFileandContext.getExistingFilemethods. - Removed some unnecessary, old code from the
Qwicapclass. - Various improvements to the Javadocs.
- Bug fix in the Hunt The Wumpus example application.
Version 1.3.2 of 16-Nov-2005
- Corrected a bug in
Form.setDataSetthat could result in double-encoding of form control values. - Updated the
Hexadecimalclass to use table lookups for its conversions. That class is not a part of the Qwicap API, but is used by Qwicap and therefore is present in the Qwicap library.
Version 1.3.1 of 20-Aug-2005
- Corrected a bug in
Results.addContentthat prevented the method from doing anything when the new content being inserted was anotherResultsobject. This also affectedResults.addContentBeforeandResults.addContentAfter, and prevented the "wumpus" demo application from working correctly.
Version 1.3 of 17-Aug-2005
- Version 1.3 has been released on SourceForge.net, and all of the required paperwork has been concurrently filed with The University, as specified by the applicable UT System policy.
- A plausible 1.3 release has been assembled and is available. It is possible that the "README.txt" file and other supporting documents will require further edits, but the code is as it should be.
- Permission to open-source Qwicap has been obtained, and I finally seem to have run out of questions for the lawyers (thanks Georgia!). Copyright notices appropriate to the Lesser GPL have been added to all source files, and some further Javadoc improvements have been made. The project is now in cleanup mode prior to filing of final paperwork and the actual open-source release.
- Modified
Results.deletesuch that it now returns an emptyResultsobject. (Originally it returned nothing.) The benefit of this modification is that it permits the application to use theResults.popmethods to recover a reference to an earlierResultsinstance (ideally, one whose elements weren't just deleted) on which it wishes to perform additional operations. - Corrected a bug in
Results.xor. Up until now, it had, in effect, been performing a subtraction, rather than an XOR. In many cases, that produced the same result as an XOR, but not in all cases. - Optimizations to the
Resultsclass: The objects are now lighter-weight than they have been, fewer objects are allocated internally, they perform almost no type-casting, and should be slightly faster here and there. - Corrected a bug in
ResultsEnumerator.nextElementwhich caused it to return an object of typeRange(or one of the many subclasses/subinterfaces that implement/extend it), rather than an object of typeMatch, as the method's documentation demanded. The type-specific methodnextMatchhas always behaved correctly. - The implementation of
ResultsEnumeratorhas been simplified, and should be more efficient now. - Removed a number of internal-use-only methods from the public API of the
Pageclass. - The performance of CSS pattern searching has nearly doubled, and the tag-hierarchy validation phase of XML parsing should also be faster.
DescendantEnumeratorno longer creates objects during the course of an enumeration.- Added a
get(CSSPatterns)method to allMarkupobjects, so that searches can be conveniently performed using "pre-compiled" CSS patterns. - Changed the implementation of
CSSPatternsCachesuch that it uses aLinkedHashMapas the basis for the cache, rather than the previous hand-coded linked-list with on-the-fly, most-recently-used element re-ordering. In some cases theLinkedHashMapis actually slower than the previous linked-list cache, but, overall, it shows a modest performance gain. Also, when the cache fills, it removes the least-recently-used elements on-the-fly, rather than in a delayed pruning pass, as was the case in the previous implementation. The Internet-Explorer-is-hopeless-rubbish automatic "button" element to "input" element conversion feature now reverses the conversion before returning from the
Qwicap.promptmethods. While this isn't necessary for pages that are setup once, and only once, beforepromptis invoked, it is necessary in the case where the "button" elements of type "submit" in the page markup are modified after the firstpromptinvocation. So, to maximize the transparency of this feature under all circumstances, the conversion is automatically reversed before returning to the client.While this change greatly increases the transparency of this feature, it is still not perfectly transparent. If client code was holding references to
Matchobjects for its "button" elements, or their contents, thoseMatchobjects would no longer refer to anything after invokingprompt, because Qwicap will have deleted those buttons, replaced them with "input" elements, sent the page to the user, then deleted the "input" elements and replaced them with new "button" elements. Given the way the Qwicap API encourages people to work, this would be a very unusual way for client code to be implemented, and reimplementing such client code so that it doesn't need to hold thoseMatchobjects acrossinputinvocations would be straightforward, so no further effort will be made to increase the transparency of this auto-convert feature. There's a limit to how severely Qwicap should be hacked to work around an inexcusably broken product like Explorer, and that limit has been reached (if not exeeded).- In support of the above, added a
convertSubmitInputsToButtonsmethod to the classesFormandMutableMarkup. - Corrected a bug in the parsing of CDATA.
Major refactoring has been performed to move classes into packages such that as many classes as possible that are for internal-use-only no longer have "public" access. For the most part, I preferred the previous organization of the code, since it did a better job of grouping related classes, but until Java acquires a variant of the "package" visibility-modifier that extends visibility to classes in sub-packages, too many internal classes have to be made "public" in order to be accessed across sub-package boundaries.
One effect of these changes that will impact existing code is the move of the
Matchclass from the "css" package to the "xml" package. The class is otherwise unchanged, so it's just a matter of adjusting "import" statements.Another effect of these changes is that the number of classes visible in the Javadoc for the API has dropped from 114 to 56. Only a few classes in the "internal use only" category are still shown. Hopefully, the API documentation will be more readily comprehensible, now that there's so much less of it to comprehend.
- Fixed a bug in
Form.isControlEnabledthat caused it to return the opposite of the correct value. - Made changes to the classes in the "css" package, and sub-packages,
that resulted in lighter-weight data structures, reduced the number of
objects used, eliminated some type-casting, eliminated the
CSSPatternMatcherclass (its duties have been taken-on by the newCSSPatterns.searchmethod), and consequently identified and fixed an old, but never-encountered, bug inMatch.get(CSSPatterns, Results). - Moved the
MutableMatchclass from the "css" package to the "mutable" package, and theImmutableMatchclass to the "immutable" package. The former move allowed theMatch.setmethod to be eliminated. - After 90 development versions, 1.3 has gone alpha.
- A bug in
MutableMatch.equalshas been corrected. It prevented some functions that relied on equality tests, likeResults.xor, from working properly under certain circumstances. This bug was introduced as a side-effect of an optimization in one of the previous development versions. A side-effect of the bug fix is that methods likexor,and,oranddistinctwill be faster than ever when dealing with mutable markup. Form.getFormIDhas been demoted from "public" to package access, since it really deals only with Qwicap's internal magic, and client code should not be depending on the behavior of that magic.- Added the method
Form.deleteChoicesto allow all of the "option" controls to be conveniently removed from a "select" control, presumably so a fresh set ofaddChoicecalls can be made to populate the "select" with new options. This method also works on "input" controls of type "radio" and "checkbox", but, because of the way HTML forms are structured, deleting these "choices" means the controls vanish from the markup entirely, andaddChoicewill not be able to add new ones. - When using any of the
Form.setControlValueorForm.setControlValuesmethods, supplying anullvalue causes the control's value to be cleared usingForm.clearControlValue. They used to just set the control's value to an empty string, but this new behavior is more consistent with the behavior ofgetControlValue, and the symmetry seems like a good idea. - Changed the
Form.clearControlValuemethod to clear the value of any type of control, not just controls whose values are user-alterable, which was its previous behavior. - Added the
Form.getControlValueandForm.getControlValuesmethods. - Made
Match.hasAttributemore efficient than it was. - Added the
Match.hasNonEmptyAttributemethod to make it easy to test whether an element has an attribute of the specified name, whose value is not empty. - Added the
Match.getAncestorOfTypemethod to allow the most recent ancestor tag of a specified type to be easily determined. - Changed the access specifiers of several classes from "
public" to package, since client code didn't need access to them. [Given a more flexible access specifier mechanism (say, one that took the package hierarchy into account), I'd gladly eliminate public access to most classes, and the product would be better for it.] - The method
Form.setControlEnablenow returns a reference to theFormobject, like almost all other methods in that class. - Changed the
XMLDocument(URLConnection)andXMLDocument(URL)constructors such that they now close the connection to the URL-specified document after they've finished reading it. (Had theURLConnectiondocumentation mentioned that it didn't close its connection when it finished reading the document content, I'd've been closing the connection all along.) - Made the
XMLDocument(URLConnection)constructor public. - Removed overlapping shortcut detection code from the decoder methods in
HTMLEntityCodec. That will make them faster in some cases. Match.getAttributewasn't decoding the attribute value it returned. It is now.- An off-by-one error in
HTMLEntityCodec.decodehas been fixed. Numeric character entities are now decoded correctly. - Removed all "form parameter"-style terminology from the
Qwicapclass, and substituted "form data set"- and "form control"-style terminology as used by the W3C in the HTML specifications. This necessitated many Javadoc changes, including the correction of some old errors, and the deprecation and replacement of a number of methods:rejectParameterandrejectParametershave becomerejectInput,getParametersis nowgetFormDataSet,hasParametersis nowhasFormDataSet, andembedParametersInMostRecentFormis nowpopulateMostRecentForm. Qwicap.rejectInputand, by extension, all methods that reject form input directly or indirectly, has been modified such that when input auto-embedding is disabled, input is still embedded into the form markup for the purpose of automatically soliciting a correction from the user, but once that's been done, the original state of the form is restored, so the client application will never know it happened. Previously, the auto-embedding took place in this case, but wasn't undone after the correction was solicited, thereby leaving the form markup in a state that the client application wouldn't expect.Removed from the
Qwicapclass the methodsgetAutoEmbedParametersandsetAutoEmbedParameters(both introduced in version 1.2), because creating a mode was a bad idea. One reason that it was a bad idea was that it interfered with code re-use by implicitly embedding an assumption about that mode into any given piece of code. Another, closely related, reason was that it couldn't easily be made page-specific. So that "feature" is history.It is replaced by a new version of the
promptmethod, and an implicit change to the behavior of the original method. The newpromptmethod accepts abooleanparameter that istrueif parameter embedding should be automatic, andfalseotherwise. (In either case, parameter embedding is automatic when a parameter is rejected, but if auto-embedding is disabled, the original form control values are automatically restored after the parameter has been rejected.) The originalpromptmethod now assumes that parameter embedding is automatic, which was the old default behavior, anyway.(This new scheme isn't ideal, however; an ideal scheme would allow separate auto-embedding settings for each form on a page. That would facilitate code re-use at the "form" level. The obvious way to solve this problem would be adding custom markup to forms that would specify this behavior to Qwicap. However, that would make their markup non-standard and prevent it from validating, while also introducing meta-data into Qwicap. Neither situation is acceptable, so the scheme remains less than ideal.)
- Added the
Form.extractDataSetmethod, which does the opposite ofembedDataSet. ArrayToStringno longer producesNullPointerExceptionswhen it encountersnullelements in arrays or collections. Instead, it outputs "null" in their places.- Remodeled the growth algorithm in
RangeListandMatchListon the algorithm employed byjava.util.ArrayList. - Improved the API documentation in many places.
- Improved some markup-related exception messages.
- The
MatchEnumeratorclass has been replaced with a new, and much more efficient, class that both enumerates faster, and doesn't fill-up the relevant markup'sMatchcache as it does so. The latter behavior not only reduces memory use, but means thatMatchcache maintenance will usually be faster (and will never be slower). The new enumerator also detects changes to its markup that occur during the enumeration and throws an exception if they occur. The original enumerator wasn't able to cope with such changes, either, but didn't detect their occurrence. - The
Formclass is no longer a subclass ofMatch. Any code that requires theMatchthat corresponds to the "form" element represented by aFormobject can use the newForm.getMatchmethod. - The way in which
MuTagWithAttributeskeeps track of its attributes has been made more efficient. (Also tweaked theAttributeEnumeratorinterface, and added a new subclass of it, in order to support those changes.) - Made the
Attributeinterface extend theNamedIteminterface, just as theRangedocumentation has always said it should. Conceptually, an attribute is a range, so this makes sense. (Hopefully there wasn't some good reason I didn't do this in the first place, or, perhaps, undid it later.) - The
MarkupEnumerationinterface has been extended to include anextRangemethod, which does exactly what thenextElementmethod does, but the type of its return value isRange, which eliminates some typecasting elsewhere in the code, and promotes type-safety. - The "cloning rule" (see
MutableMarkup.insert) has been relaxed. Originally, no element could exist more than once in the same body of markup, so, for instance, duplicating a row of a table meant creating clones of all the elements in the duplicate row. However, over the course of Qwicap's evolution, a set of features have been put in place for various other reasons that make the cloning rule unnecessary where immutable elements are concerned. So, now only mutable elements are cloned, which will save memory (less redundancy), and time (less cloning). [Within this very limited context, cloning isn't necessary for mutable elements, either, but a failure to clone them would lead to very interesting behaviors that would make the Qwicap templating engine unusable in practice. And that would be bad.] - The way in which
ImTagWithAttributeskeeps track of its attributes has been made more efficient. - Documented all public methods of the
Formclass, and adapted most of the existing documentation to the recent change in terminology from "parameters" to "controls". - Changed a number of class and method names to bring Qwicap's use of HTML "form"
related terminology more in line with official W3C terminology as used in the HTML
specifications. So,
WebParameterswas renamed toFormDataSet(see "form data set" in the spec.),WebParameterwas renamedFormControlValue(not because the W3C uses that exact term, but because the closest it gets to a name for such things is "control-name/current-value pair"),FormElementInfobecameFormControlInfo, and all uses of the word "Parameter" were removed from method names in theFormclass and replaced, for the most part, with the term "Control", e.g. the methodsetParametershas becomesetControlValues, though the methodembedParametershas becomeembedDataSet. - Added the
Nullclass which provides a set of static utility methods that perform common tasks associated with the handling ofnullvalues. - Finally documented the
HTMLEntityCodecclass, and also changed itssetEncodingmethod to support method invocation chaining by having it return a reference to its instance of theHTMLEntityCodecclass. (Previously, it returned nothing.) - The
Form.clearValuesmethod's purpose was to clear the values of all controls in a particular form whose values were user-alterable. To that end, it did not clear the values of buttons, and hidden input controls. Its failing was that it did clear the values of disabled controls (controls with a "disabled" attribute). Since those controls aren't user-alterable, that behavior contradicted the stated purpose of the method. So, the method has been eliminated, and replaced with a new method,Form.clearControlValuesthat makes its behaviors more explicit, and controllable. - Fixed a bug, introduced earlier in the 1.3 development cycle as part of the
Internet-Explorer-is-hopeless-rubbish work-around for "button" elements, that
caused the method
Form.embedParametersto be overzealous and embed parameter values into "button" elements. Since "button" elements don't have user-modifiable values, this was unnecessary, and had destructive effects if multiple buttons had the same name. - When passed an error message object that is any subclass of
Markup, the variousQwicap.rejectParametermethods will now insert the rejected parameter's value into the error message anywhere a tag is found with the class "qwicap-param-value". Specifically, the content of such tags is replaced with the string representation of the parameter value(s). - Corrected a bug in
Results.setContentthat prevented it from working correctly when the content to be inserted was identified by aResultsobject containing more than one match. - Added a
printmethod to theMarkupclass to facilitate debugging. MutableMarkup.insertwill now acceptResultsobjects as a means of specifying the new material to be inserted. Ordinarily, such cases are specially handled by various methods in theResultsclass, e.g.setContent,addContent. This change means that the expected insert functionality is available even when you're not going through aResultsobject.- Wherever it can be done quickly,
HTMLEntityCodecpre-screens material to be encoded and decoded to determine whether the encoding/decoding is unnecessary and can be skipped. This can save time and completely eliminate memory allocations from applicable invocations. - Added the methods
getLongandgetDoubleto theMatchclass. They do just whatgetTextalready does, but they attempt to interpret the text as an integer, or floating-point, value. - Finally got around to dealing with the character encoding issues associated with attribute values. (However, this new implementation might be performing encoding that isn't absolutely necessary.) The new code only acts on attributes that you've created or modified since the document was loaded. So, if you have invalid attribute values in your original document, and you don't alter them before writing-out the document, they'll be invalid in the output, too.
- Made the
Qwicap.htmlEncodemethod static, because there was no reason to have made it an instance method in the first place, and added a statichtmlDecodemethod in the name of symmetry. - Corrected an omission in the tag hierarchy validation code that caused it to attempt to pop from an empty stack when it encountered an entirely isolated end tag.
- The
ALStackclass now throwsEmptyStackExceptionwhen attempting topeekorpopfrom an empty stack. Previously, a less informative exception was thrown from the depths of theArrayListclass. - Reduced typical memory usage by
ImmutableMarkupand its descendants, notablyXMLString. - Added a
lengthmethod toXMLString. It returns the number of characters in the markup-bearing object that was passed toXMLString's constructor. - Increased the efficiency of the mutable content
writemethod. - Corrected a bug in
Results.getTextthat could produce aStringIndexOutOfBoundsException. - Corrected an omission in the tag hierarchy validation code that prevented it from complaining about a document that ends before a full complement of end tags were found.
- Added to
ImmutableMarkupa new constructor that accepts aMutableMarkupobject as its sole parameter. The new constructor uses as-is all of the immutable elements present in the mutable document, and converts the mutable elements to new immutable representations. - Reimplemented
MutableMarkup.getImmutableto use the aforementioned, newImmutableMarkupconstructor. - Corrected a problem that led to a
NullPointerExceptionwhen rejecting parameters on a page that had no current form, a situation that doesn't arise in normal usage. - Fixed a bug that prevented a form parameter value from being automatically embedded into page markup when a rejected parameter value was corrected by the user. Obviously, this only applies in situations where automatic parameter embedding is enabled, but since it's enabled by default these days, that's quite a lot of situations.
- Removed some obsolete code from the various parameter-oriented "get" methods
of the
Qwicapclass. - Implemented CSS pattern caching for all markup objects. Previously, everytime
a CSS pattern
string was passed to
Markup.getorResults.getit had to be parsed and a set of objects created to implement the pattern (for lack of a better term, call this "compiling"). Now, however, a cache of "compiled" patterns is maintained for each body of markup, so parsing and compiling takes place only on the first occasion a CSS pattern is used on any given markup object. While performance without pattern caching was good, it should be better now, especially wheregetinvocations occur in loops. - Improved the performance of
ImmutableMarkupand, especially,MutableMarkupby replacing theArrayListobjects they'd been using internally with custom objects which are optimized for their respective data types and purposes. - Added a new constructor to
XMLStringwhich accepts an arbitraryObjectas the source of the XML markup string that is to be parsed. Specifically, the object'stoStringmethod is invoked, and theStringit returns is parsed. - Added a new constructor to
XMLDocumentwhich accepts aURLfrom which the XML markup should be retrieved. Previously, it was necessary to use theQwicap.getDocument(URL), orXMLCache.getDocument(URL)methods to conveniently instantiate markup from aURL. - Added a new constructor to
ImmutableMarkupwhich accepts only one parameter: a character array. The entire array is parsed. - Overrode the
toStringandwritemethods inImmutableMarkupto make them more efficient than the general-purpose implementations of those methods that were inherited from theMarkupclass. - Added new Javadoc documentation to a number of markup-related classes, and made a small improvement to the "Qwicap Templating Introduction" document.
- Added the
ArrayToStringutility class. It converts an array orCollection(or any object) to a pleasantly human-readable string, but defers that conversion work until thetoStringmethod is called, which makes this class a very efficient way to include arrays in log entries produced by theLoggerclass; if the log-level is such that the log entry is discarded, the nitty, gritty work of converting the array orCollectionto a string never takes place. - No one should use Internet Explorer for a lot of reasons, including
that it's buggy and not standards-compliant. However, because it's hard
to ensure that one's users will be running high-quality browsers, Qwicap
now includes a workaround for a large Internet Explorer bug: its inability
to correctly handle forms with more than one "button" element of type
"submit". To work around this problem without forcing developers to
rewrite, or dumb-down, their pages, the
Qwicapclass now provides theconvertSubmitButtonsToInputsmethod. - Rudimentary namespace support has been added to Qwicap's XML parser. Namespaces in immutable markup are handled correctly. Namespace support in mutable markup is incomplete. For instance, inserting markup from one namespace into an area of a document that is assigned to another namespace will work correctly in the sense that the insert will take place, and namespace-aware selectors used on the document will yield correct results, but when the markup is converted to text, Qwicap won't notice the transition from one namespace to another and won't therefore generate a new namespace declaration attribute where the transition between namespaces occurs.
- Two elements of CSS3 syntax have been embraced in order to support namespaces: (1) The "@namespace" rule specifies a mapping between a namespace URI and an abbreviated name to represent it. (2) The "|" delimiter in CSS selectors for elements (not attributes at this time) which separates an abbreviated namespace name, as specified in one of the aforementioned namespace "at rules" from the rest of the CSS selector. So, a namespace aware selector string to select all of the XHTML paragraph elements in a document would look like: "@namespace xhtml url(http://www.w3.org/1999/xhtml); xhtml|p".
Version 1.2.3 of 28-Sep-2004
- Altered the way in which Qwicap embeds its hidden form- and page-ID input elements into forms. Previously they were inserted immediately before the form's first control element. If that first control element was wrapped in a "label" element, the "label" element would end-up wrapping two hidden "input" elements in addition to the control element it was supposed to be wrapping. Unfortunately, that confused the Firefox browser. Now, if the first control element of a form is wrapped in a "label" element, the hidden form- and page-IDs are embedded immediately before the "label" element.
Version 1.2.2 of 28-Sep-2004
- Improved the class
documentation for the
Resultsclass. It now provides a break-down of the methods grouped by their purposes. - Improved the error messages supplied by many exceptions.
- Corrected a bug in some file caching logic.
- Added the
IF,ELSE, andENDIFmethods to theResultsclass in order to support in-line logic within method invocation chains. Whentrueis passed toIF, it returns an equivalent to the currentResultsobject, but whenfalseis passed, it returns an emptyResults. TheELSEmethod reverses that outcome, and theENDIFmethod returns theResultsobject on whichIFwas invoked. NestedIFinvocations are not supported. Also unsupported is use of theELSEandENDIFmethods either out-of-sequence, or without a precedingIFinvocation. - The Intellij IDEA project files included with the Qwicap source have been upgraded from version 3 to version 4.5 format.
- Added the
Form.setParametersmethods to provide some symmetry with the pre-existingResults.setContentsandResults.setAttributesmethods. - Changed all of the parameter-oriented methods of the
QwicapandFormclasses such that where they used to accept parameter values asStringobjects, they now accept any type of object. Since the values are inevitably sent and received as text, it is a given that whatever type of object is passed as a parameter value, Qwicap will end-up converting it to aStringby calling itstoStringmethod. Nonetheless, by accepting values asObjects, things should occasionally be more convenient for application developers, and auto-boxing should further increase the convenience level, when it arrives. - Removed the
Qwicap.checkExceptionmethod which was useless to clients, and unused by any of the Qwicap code. - Added the
Qwicap.getBooleanmethods to retrieve parameters that may have at most two values and translate them into the primitivebooleantype. - Modified the various parameter retrieval methods in
Qwicapsuch that the error messages they generate use curved left- and right-double quotes to enclose their values, instead of the conventional, straight double-quote character. - Improved the class
documentation for the
Qwicapclass. It now provides a break-down of the methods grouped by their purposes. - Improved the
MutableMatchclass such that it throws an exception (NoSuchElementException) with a long, and hopefully informative, error message whenever an operation is attempted on a markup element that no longer exists. (It used to throw the same exception, but without any message.) One way to encounter this error is to perform a multi-pattern search, e.g."*.these, *.those", on a body of markup where the search patterns produce aResultsobject containing overlapping sets of matches, and then to invokeResults.delete. Among the overlapping matches, the first delete of any given element will succeed, but the next one will throw the aforementioned exception, since the element to be deleted no longer exists. This is a rare situation, and easily avoided by using theResults.distinctmethod before thedelete, but was very confusing in the absence of an explanatory error message. - Added the
Qwicap.rejectParameters(String[] ParamNames, String[] ParamValues, Object ErrorMessage)method, and recoded all of the pre-existingQwicap.rejectParametermethods so that they are merely front-ends for the newrejectParametersmethod. Thus, there is only one body of parameter-rejection logic. - Removed the
Qwicap.rejectParameters(String[] ParamNames, Object ErrorMessage)method that was introduced in version 1.2. Use the newQwicap.rejectParameters(String[] ParamNames, String[] ParamValues, Object ErrorMessage)method instead. You can passnullas theParamValuesparameter to achieve the same result. - Enhanced the code that searches-out the (potential) hierarchy of labels
associated with any control in a form. It now searches outside of the
formelement that contains a control, just in case theformis contained within afieldsetelement. (When the code was originally written, I hadn't realized that usingfieldsetoutside of aformwas legal, which it is, even in XHTML 1.0 Strict.) - Improved the parameter rejection logic such that the error messages are
inserted just before the outer-most enclosing element (
formorfieldset) of the controls that supplied the rejected parameters. - Improved the parameter rejection logic such that parameters that did not originate in the most recently submitted form can also be rejected, provided that the current page contains at least one form that could have supplied them. This is a big help with pages that contain multiple forms which are used together.
Version 1.2.1 of 30-Jul-2004
- The
Qwicap.getIntandQwicap.getLongmethods weren't displaying their bad-parameter error messages properly in some situations. This has been fixed. - In the Qwicap API documentation, and in some comments in the Qwicap source code, instances of the word "get" had been replaced by the word "getInstance", due to the inattentive application of an aggressive refactoring tool. These have been corrected.
Version 1.2 of 29-Jul-2004
- The
Qwicap.getVersionmethod has been added to provide developers an indication of which version of Qwicap they're using. IncompleteTagExceptionnow provides an informative error message, instead of no message at all.- Added the
Qwicap.getFormmethod which returns aFormobject for manipulating the form that supplied the current parameters (the parameters available by callingget,getString,getInt,getDouble, etc.). - Added the
Qwicap.rejectParametersmethod to handle cases where multiple form elements contain the data that caused the form input to be rejected. Added theForm.getFormElementsmethod to supportQwicap.rejectParameters. The
Qwicap.rejectParametermethod has been changed such that the error message parameter it accepts can be any class of object, not justStringas used to be the case. Internally, the error message is inserted usingMutableMarkup.insertwhich has a number of useful behaviors, including automatic HTML-encoding ofStringobjects, and embedding of the stack-traces fromThrowableobjects, such as exceptions. The one drawback of this change is that it eliminates the feature of the previousrejectParameterimplementation that allowed the supplied error message string to be an XHTML fragment into which things like the name of the form field that supplied the bad parameter could be automatically embedded. That embedding functionality survives, but only when the supplied object is a subclass ofMarkup(XMLStringcan be quite convenient in this situation). In order to regain the convenience of passing XHTML fragments asStringobjects, use the newQwicap.rejectParamter(String ParamName, String ParamValue, boolean ErrorMsgIsXHTMLFragment, String ErrorMsg)method with the parameterErrorMsgIsXHTMLFragmentset totrue.The previous
rejectParameterimplementation suffered from two shortcomings: (1) a lack of flexibility in that it only accepted error messages as strings, and (2) by making the HTML-encoding of the error message string the responsibility of the developer, it was likely to give rise to situations where strings were accidentally passed without the necessary encoding, an oversight which could result in XML parsing exceptions, or cross-site scripting attacks. A developer could still create either problem by passing a bad error message string to the newrejectParametermethod with itsErrorMsgIsXHTMLFragmentparameter set totrue, but at least they'll have to explicitly assert that they're supplying a valid XHTML fragment (which indicates to Qwicap that HTML-encoding is not to be performed), rather than accidentally overlooking the issue.- The
Qwicap.embedParametersInMostRecentFormmethod is now called automatically byQwicap.promptafter each set of form parameters is received. I believe this will be more consistent with developer expectations and/or convenience than making developers invoke it manually. Where this automatic behavior might be inappropriate, or useless, it can be controlled using the newQwicap.setAutoEmbedParametersmethod. The state of the behavior can be determined using the newQwicap.getAutoEmbedParametersmethod. - Setting the value of an "input" form element of type "checkbox" or "radio" now works correctly. Previously, the value of those elements was first cleared by deleting the "checked" (correct) and "value" (incorrect) attributes of the specified group of those elements (all those with matching "name" attributes), then setting the "checked" attribute of the approiate radio/checkbox item. Unfortunately, with the "value" attribute deleted, the code would never find the appropriate radio/checkbox item, and even if it had, the item would have been useless as a form element, since it no longer had a value to supply.
- The CSS2 parser has been made more correct. The CSS2 specification appears to be ambiguous on a number of subtle points, so there doesn't seem to be any way to say with certainty that the parser is correct even now, but it is more correct than it was. The most prominent improvement in the CSS2 parser is that escape sequences are now supported.
- The ":lang()" pseudo-class is now supported in CSS2 selectors.
- The
Form.disableParameterandForm.enableParametermethods have been added to provide abstract form element disabling/enabling functionality. - Methods like
Results.setContentthat ultimately invokeMutableMarkup.insert, will now acceptnullin place of a valid content object. The string "null" will be inserted in such cases. Previously, aNullPointerExceptionwas thrown. - Methods like
Results.setContentthat ultimately invokeMutableMarkup.insert, will now accept arrays and objects that implement theCollectioninterface. In both cases, the contents will be interated through, with each element converted to a string, and commas inserted between elements. Whenever an element is found to be an array or aCollectionthe conversion process proceeds recursively, with the new material enclosed by brackets. (The elements ofbyteorBytearrays, will be displayed as unsigned decimal quantities. This seemed like it would be more useful to most developers than displaying signed quantities.) - Methods like
Results.setContentthat ultimately invokeMutableMarkup.insert, will now acceptThrowableobjects, and all subclasses thereof, notablyException. If theThrowablehas a message, that message is inserted. If it does not, the fully-qualified name of theThrowable's class is inserted. In either case, theThrowable's stack trace is then marked-up as an XHTML comment block and inserted, so the end-user will not see it, but the developer can view the page source to retrieve the stack trace. - The
Qwicap.reportExceptionmethod has been added. When you encounter anException(or anyThrowable) that you want to catch and report to the user, pass it toreportExceptionand the next time you invokeQwicap.promptorQwicap.goodbyean error message describing the exception will automatically be inserted as the first item in the document's "body" element. (Also, the associated stack trace will be embedded in a comment block within that error message.) If the same document object is subsequently passed toQwicap.promptorQwicap.goodbye, the error message will be removed before the document is transmitted to the client. - The
Qwicap.hasParametersmethod has been added. It returnstrueif any form parameters are available, orfalseotherwise.
Version 1.1 of 29-Apr-2004
- "Page Abandonment" - It is now possible to use a browser's "back" button to return to a previous page generated by a Qwicap application and to successfully interact with that page, provided that the method that supports the page is still in the call chain, and the page in question is the most recent version of itself. This process is handled transparently to client code. Until now, going back to previous pages wasn't possible.
- "Form Abandonment" - It is now possible, on multi-form pages, to interact with a different form even while the form with which you had been interacting is in an input correction loop. This process is handled transparently to client code.
- The
Qwicap.parameterRejectedmethod has been removed. Use the new Prompt Pattern in place of it and all associated logic. This change was required to make transparent form and page abandonment possible. - HTTP file upload is integrated into Qwicap, thanks to the Apache Jakarta Project's
Commons FileUpload library.
Just set a "form" element's "enctype" attribute to
"multipart/form-data", and include an "input" element whose
"type" attribute is "file", and you're in business. Uploaded files are handled like any
other form parameters, so their contents can be retrieved, where appropriate, with
pre-existing parameter retrieval methods like
Qwicap.getString, while more complete functionality is available from the newQwicap.getUploadedFilemethod. By default, files up to 16 K are accepted and stored in memory, while larger files are rejected. TheQwicap.setUploadedFileLimitsmethod is used to alter upload-related settings. - The
Qwicap.hasmethod was added. It tests for the presence of a particular form parameter in the current parameter set, returningtrueif it exists, andfalseotherwise. - The
Form.addChoicemethod was added. It adds a choice to a pre-existing "select" element, group of radio buttons, or checkboxes. To supportaddChoice, theForm.createChoicemethod was added. It creates the markup for a new choice ("option", "radio", or "checkbox"). - Improved white-space handling when using methods that extract text from a section
of XHTML markup, for instance
Results.getText. - The previous HTML character encoder has been replaced by a new HTML character codec.
The codec handles all
character entities defined in the HTML 4 spec. This alone is a significant
improvement, but, because the codec also does decoding (or it wouldn't be a codec),
methods like
Results.getText, which extract text from markup, now use it to map encoded characters to their Unicode equivalents. This is important because it allows such extracted text, or any portions thereof, to be inserted back into markup without becoming double-encoded. - A
getTypemethod was added to several classes dealing with XHTML markup includingMatchandResults. It returns the type of the referenced tag, for example: "a", "img", "table", "form". - The
MutableMarkup.getImmutablemethod was added. It convertsMutableMarkupto a newImmutableMarkupobject by rendering the mutable material to a new backing store, and creating a newImmutableMarkupobject to represent its contents. This provides a pleasant symmetry with the pre-existingImmutableMarkup.getMutablemethod, and is probably terribly useful for something. - Automatic document titling - Because markup isn't allowed in the content of XHTML "title" tags, the Qwicap templater can't be used to do convenient things like inserting material into "span" elements in titles. To work around this problem, Qwicap now automatically sets the contents of a document's "title" tag to the text of all tags in the body of a document that have been assigned a class of "qwicap-title". (If no tags with that class are found, the contents of the "title" element are left untouched.) One way to utilize this feature is to assign the document's "h1" tag the class "qwicap-title", then use the templater to build its contents. Just before sending the document to the client, Qwicap will automatically set the "title" tag to the text of the "h1" tag. Alternately, if it weren't appropriate for the "h1" tag and title to be identical, something like an invisible paragraph could be used instead of the "h1".
Qwicap.clearMostRecentFormandQwicap.embedParametersInMostRecentFormused to throw an exception when the internal page stack was empty; now, they do nothing in that case.- Added the method
Qwicap.getDocument(URL)to make loading documents from URLs convenient. - Many internal changes to support page and form abandonment.
- Ant build scripts improved. They now handle compilation of the source.
- Sample code updated.
- Many improvements to the documentation.
Version 1.0.2 of 13-Mar-2004
-
XMLCachecan now read documents fromURLs, which provides a work-around for security manager prohibitions against local file-system access. Note that while the cache automatically updates when a cached file is found to have been modified, the same is not true for documents retrieved from URLs; changes to them are not detected. -
XMLDocumentcan now read documents fromInputStreams. Previously, it could only read them from files. -
Results.or,Results.and, andResults.xormethods added, for computing the union, intersection, and, um, whatever the opposite of an intersection is called, for any two Results objects. The resultant set is returned in a new Results object. -
Convenience method
Results.setAttributesadded (it parallels the existingResults.setContentsmethod). - Corrected an omission that could prevent forms containing one or more "button" elements from being handled correctly.
-
Exposed the internal
Formclass such that it can be utilized in code that uses only the Qwicap templater, rather than the complete Qwicap system. TheFormclass greatly simplifies certain aspects of the manipulation of forms. See theFormclass, along with methodsMutableMarkup.getFormandResults.getForm. (Also had to expose theWebParametersclass.) - When inapplicable parameters are sent to the current page's form, typically because the user clicked the "back" button in their browser and then attempted to interact with a form in one of the earlier pages, an explanation of the problem is logged, the parameters are discarded, and the current page is automatically re-sent to the client. Previously, an exception was thrown and the client received no page at all.
-
Results.addContentAfterwas doing exactly the same thing asResults.addContentBefore. It now does what it's supposed to do. -
HTMLEntityMapno longer regards tabs as unprintable characters. - Minor tweaks and corrections to the API documentation.
Version 1.0.1 of 13-Nov-2003
-
Authentication & Authorization harness added. See the
Auth2Schemeinterface documentation for details. (Ask about Fat Cookie support.) -
Replaced all calls to
System.out.printlnwith calls to thejava.util.loggingpackage. - Changed the roots of package names from "edu.utexas.its.tn.qwicap" to "edu.utexas.its.eis.tools.qwicap".
- Broke-out the example code into separate projects that are smaller, and more-comprehensible than the original all-in-one distribution.
- Improved the associated Ant build scripts (they now produce WAR files, for instance), but you still have to perform the actual "building" of the code by using the IntelliJ "Make Project" feature before running the Ant scripts. (Yes, this ought to be fixed one of these days.)
- A few, small bug fixes.
Version 1.0 of 30-Sep-2003
- First release.
Version 1.0d2 of 10-Jun-2003
- Work begins on the CSS selector engine.
Version 1.0d1 of 6-Jun-2003
- Work begins on the XML templating engine.
Version 1.0d0 of 4-Jun-2003
- Work begins with code to prove the thread-for-each-session, block-to-prompt, unblock-on-form-data-set-arrival concept.