You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Scott Boag/CAM/Lotus <Sc...@lotus.com> on 2000/10/10 04:05:55 UTC

[XalanJ2] Changes to threading, & note about SAX ->TrAX processing

The issues that Davanum found (Re: [C2] [Xalan2] For Invalid XML ,
Transformer should throw exceptions) sent me down the path of looking into
the parse events/transformer threading model.  What we were doing is
creating the XMLReader on a secondary thread, then checking to see if a
given requested child is ready on the main transformer thread, and waiting
for the secondary thread if it is not.  This obviously won't work in the
case where our input is SAX events... in this case we were getting no
benifit from the incremental model.  So, I changed things around so that
the parse events are on the main thread, and the transform is on the
secondary thread.  The source tree is created in
SourceTreeHandler#startDocument, and in SourceTreeHandler#endDocument the
thread may have to go into a wait state until the transform is complete (I
think this is the right place for this... at least the transform methods
should not end until the transformation is complete... I could do the wait
there, but I figure it will be problematic if a ContentHandler completes
before the transformation is done also).

In the SourceTreeHandler each SAX method is synchronized with the
transformer object, and Parent#getChild(int i), Parent#hasChildNodes(),
Parent#getChildCount(), ElementImpl#getChildCount(), and
DocumentImpl#getElementById all may be synchronized with the transformer on
the secondary transform thread.  Basically, the transform thread can't get
a child if the main thread is in a ContentHandler SAX method.  I think this
is good and correct, though I'm a little worried about synchronization
overhead.  If anyone that knows a lot about threads wants to take a look at
this stuff, I would be highly appreciative.

For Xerces2, if they do a pull API (i.e. parser.parseSomeMore(4096)) then
we can do away with the threading in the case of where Xalan is using a
parser.  But this won't help in the case of SAX events.  I should probably
do a SynchronizedSourceTreeHandler and SynchronizedParent in anticipation
of this.

Also, when running our regression tests with the SAX->TrAX model, I found
that the base URI of the source document was not being set, and there was
no way to set it.  Accordingly, Xalan now allows the caller to set the base
URI via setProperty.  The following is a sample of how to call the
SAX->TrAX API, so that everything will be resolved correctly (assuming the
templates and transformer have already been set up):

              OutputFormat format = templates.getOutputFormat();
              Serializer serializer =
SerializerFactory.getSerializer(format);
              serializer.setOutputStream(outputStream);
              transformer.setContentHandler(serializer.asContentHandler());
              transformer.setProperty
("http://xml.apache.org/xslt/sourcebase",
                                      inFileName);

              XMLReader reader = XMLReaderFactory.createXMLReader();

              reader.setFeature
("http://xml.org/sax/features/namespace-prefixes", true);
              reader.setFeature
("http://apache.org/xml/features/validation/dynamic", true);

              ContentHandler chandler = transformer.getInputContentHandler
();
              reader.setContentHandler(chandler);

              if(chandler instanceof org.xml.sax.ext.LexicalHandler)
                reader.setProperty
("http://xml.org/sax/properties/lexical-handler", chandler);

              reader.parse(inFileName);

One bug left is that the transformer can't switch to HTML output mode if
the first output element is "HTML", as per spec.  Since the first output
element can be created dynamically, this is imposible to determine in
getOutputFormat, and I don't see how we can change serializers dynamically.

-scott