mkwan 2003/06/25 12:55:46
Modified: java/src/org/apache/xalan/xsltc/dom LoadDocument.java
MultiDOM.java
java/src/org/apache/xalan/xsltc/runtime
AbstractTranslet.java
java/src/org/apache/xalan/xsltc/trax TemplatesImpl.java
Log:
Implement a feature to cache the DTM for the stylesheet in
the Templates object. This improves the case where document('')
is used. In this case the DTM for the stylesheet is only built
once per thread. It can be reused by multiple transformers
created by the sample Templates.
Revision Changes Path
1.22 +89 -33
xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java
Index: LoadDocument.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- LoadDocument.java 23 Jun 2003 19:46:03 -0000 1.21
+++ LoadDocument.java 25 Jun 2003 19:55:45 -0000 1.22
@@ -64,16 +64,16 @@
import java.io.FileNotFoundException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.DOMCache;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.runtime.AbstractTranslet;
+import org.apache.xalan.xsltc.trax.TemplatesImpl;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMAxisIterator;
+import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMDefaultBase;
import org.apache.xml.dtm.ref.EmptyIterator;
import org.apache.xml.utils.SystemIDResolver;
@@ -142,9 +142,30 @@
baseURI =
SystemIDResolver.getAbsoluteURIFromRelative(xslURI);
String href = (String)arg;
- if (href.length() == 0)
- href = "";
- return document(href, baseURI, translet, dom);
+ if (href.length() == 0) {
+ href = "";
+ // %OPT% Optimization to cache the stylesheet DOM.
+ // The stylesheet DOM is built once and cached
+ // in the Templates object.
+ TemplatesImpl templates =
(TemplatesImpl)translet.getTemplates();
+ DOM sdom = null;
+ if (templates != null) {
+ sdom = templates.getStylesheetDOM();
+ }
+
+ // If the cached dom exists, we need to migrate it
+ // to the new DTMManager and create a DTMAxisIterator
+ // for the document.
+ if (sdom != null) {
+ return document(sdom, translet, dom);
+ }
+ else {
+ return document(href, baseURI, translet, dom, true);
+ }
+ }
+ else {
+ return document(href, baseURI, translet, dom);
+ }
} else if (arg instanceof DTMAxisIterator) {
return document((DTMAxisIterator)arg, null, translet, dom);
} else {
@@ -156,9 +177,16 @@
}
}
-
private static DTMAxisIterator document(String uri, String base,
AbstractTranslet translet, DOM dom)
+ throws Exception
+ {
+ return document(uri, base, translet, dom, false);
+ }
+
+ private static DTMAxisIterator document(String uri, String base,
+ AbstractTranslet translet, DOM dom,
+ boolean cacheDOM)
throws Exception
{
try {
@@ -189,40 +217,35 @@
// Check if we can get the DOM from a DOMCache
DOMCache cache = translet.getDOMCache();
- DOM newdom;
+ SAXImpl newdom;
mask = multiplexer.nextMask(); // peek
if (cache != null) {
- newdom = cache.retrieveDocument(base, originalUri, translet);
+ newdom = (SAXImpl)cache.retrieveDocument(base, originalUri,
translet);
if (newdom == null) {
final Exception e = new FileNotFoundException(originalUri);
throw new TransletException(e);
}
} else {
// Parse the input document and construct DOM object
- // Create a SAX parser and get the XMLReader object it uses
- final SAXParserFactory factory = SAXParserFactory.newInstance();
- final SAXParser parser = factory.newSAXParser();
- final XMLReader reader = parser.getXMLReader();
- try {
- reader.setFeature(NAMESPACE_FEATURE,true);
- }
- catch (Exception e) {
- throw new TransletException(e);
+ // Trust the DTMManager to pick the right parser and
+ // set up the DOM correctly.
+ XSLTCDTMManager dtmManager =
(XSLTCDTMManager)multiplexer.getDTMManager();
+ newdom = (SAXImpl)dtmManager.getDTM(new StreamSource(uri),
+ false, null, true, false,
+ translet.hasIdCall(), cacheDOM);
+
+ // Cache the stylesheet DOM in the Templates object
+ if (cacheDOM) {
+ TemplatesImpl templates =
(TemplatesImpl)translet.getTemplates();
+ if (templates != null) {
+ templates.setStylesheetDOM(newdom);
+ }
}
-
- // Set the DOM's DOM builder as the XMLReader's SAX2 content
handler
- XSLTCDTMManager dtmManager = (XSLTCDTMManager)
- ((DTMDefaultBase)((DOMAdapter)multiplexer.getMain())
- .getDOMImpl()).m_mgr;
- newdom = (SAXImpl)dtmManager.getDTM(
- new SAXSource(reader, new InputSource(uri)),
- false, null, true, false,
translet.hasIdCall());
-
+
translet.prepassDocument(newdom);
-
- ((SAXImpl)newdom).setDocumentURI(uri);
+ newdom.setDocumentURI(uri);
}
// Wrap the DOM object in a DOM adapter and add to multiplexer
@@ -230,11 +253,10 @@
multiplexer.addDOMAdapter(domAdapter);
// Create index for any key elements
- translet.buildKeys(domAdapter, null, null,
- ((SAXImpl)newdom).getDocument());
+ translet.buildKeys(domAdapter, null, null, newdom.getDocument());
// Return a singleton iterator containing the root node
- return new SingletonIterator(((SAXImpl)newdom).getDocument(), true);
+ return new SingletonIterator(newdom.getDocument(), true);
} catch (Exception e) {
throw e;
}
@@ -260,6 +282,40 @@
union.addIterator(document(uri, baseURI, translet, dom));
}
return(union);
+ }
+
+ /**
+ * Create a DTMAxisIterator for the newdom. This is currently only
+ * used to create an iterator for the cached stylesheet DOM.
+ *
+ * @param newdom the cached stylesheet DOM
+ * @param translet the translet
+ * @param the main dom (should be a MultiDOM)
+ * @return a DTMAxisIterator from the document root
+ */
+ private static DTMAxisIterator document(DOM newdom,
+ AbstractTranslet translet,
+ DOM dom)
+ throws Exception
+ {
+ DTMManager dtmManager = ((MultiDOM)dom).getDTMManager();
+ // Need to migrate the cached DTM to the new DTMManager
+ if (dtmManager != null && newdom instanceof DTM) {
+ ((DTM)newdom).migrateTo(dtmManager);
+ }
+
+ translet.prepassDocument(newdom);
+
+ // Wrap the DOM object in a DOM adapter and add to multiplexer
+ final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
+ ((MultiDOM)dom).addDOMAdapter(domAdapter);
+
+ // Create index for any key elements
+ translet.buildKeys(domAdapter, null, null,
+ newdom.getDocument());
+
+ // Return a singleton iterator containing the root node
+ return new SingletonIterator(newdom.getDocument(), true);
}
private static String getBaseFromURI( String uri){
1.29 +10 -1
xml-xalan/java/src/org/apache/xalan/xsltc/dom/MultiDOM.java
Index: MultiDOM.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/MultiDOM.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- MultiDOM.java 23 Jun 2003 15:58:17 -0000 1.28
+++ MultiDOM.java 25 Jun 2003 19:55:46 -0000 1.29
@@ -87,6 +87,7 @@
private DOM[] _adapters;
private DOMAdapter _main;
+ private DTMManager _dtmManager;
private int _free;
private int _size;
@@ -283,6 +284,10 @@
DOMAdapter adapter = (DOMAdapter)main;
_adapters[0] = adapter;
_main = adapter;
+ DOM dom = adapter.getDOMImpl();
+ if (dom instanceof DTMDefaultBase) {
+ _dtmManager = ((DTMDefaultBase)dom).getManager();
+ }
// %HZ% %REVISIT% Is this the right thing to do here? In the old
// %HZ% %REVISIT% version, the main document did not get added
through
@@ -400,6 +405,10 @@
public int getDocument()
{
return _main.getDocument();
+ }
+
+ public DTMManager getDTMManager() {
+ return _dtmManager;
}
/**
1.48 +28 -4
xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
Index: AbstractTranslet.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- AbstractTranslet.java 1 Apr 2003 21:28:38 -0000 1.47
+++ AbstractTranslet.java 25 Jun 2003 19:55:46 -0000 1.48
@@ -71,6 +71,7 @@
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;
+import javax.xml.transform.Templates;
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.DOMCache;
@@ -102,6 +103,9 @@
protected String[] namesArray;
protected String[] namespaceArray;
+ // The Templates object that is used to create this Translet instance
+ protected Templates _templates = null;
+
// Boolean flag to indicate whether this translet has id functions.
protected boolean _hasIdCall = false;
@@ -361,7 +365,7 @@
// Container for all indexes for xsl:key elements
private Hashtable _keyIndexes = null;
- private KeyIndex _emptyKeyIndex = new KeyIndex(1);
+ private KeyIndex _emptyKeyIndex = null;
private int _indexSize = 0;
/**
@@ -416,13 +420,21 @@
*/
public KeyIndex getKeyIndex(String name) {
// Return an empty key index iterator if none are defined
- if (_keyIndexes == null) return(_emptyKeyIndex);
+ if (_keyIndexes == null) {
+ return (_emptyKeyIndex != null)
+ ? _emptyKeyIndex
+ : (_emptyKeyIndex = new KeyIndex(1));
+ }
// Look up the requested key index
final KeyIndex index = (KeyIndex)_keyIndexes.get(name);
// Return an empty key index iterator if the requested index not found
- if (index == null) return(_emptyKeyIndex);
+ if (index == null) {
+ return (_emptyKeyIndex != null)
+ ? _emptyKeyIndex
+ : (_emptyKeyIndex = new KeyIndex(1));
+ }
return(index);
}
@@ -623,6 +635,10 @@
_auxClasses.put(auxClass.getName(), auxClass);
}
+ public void setAuxiliaryClasses(Hashtable auxClasses) {
+ _auxClasses = auxClasses;
+ }
+
public Class getAuxiliaryClass(String className) {
if (_auxClasses == null) return null;
return((Class)_auxClasses.get(className));
@@ -639,4 +655,12 @@
public boolean hasIdCall() {
return _hasIdCall;
}
+
+ public Templates getTemplates() {
+ return _templates;
+ }
+
+ public void setTemplates(Templates templates) {
+ _templates = templates;
+ }
}
1.28 +42 -8
xml-xalan/java/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
Index: TemplatesImpl.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- TemplatesImpl.java 20 May 2003 14:37:13 -0000 1.27
+++ TemplatesImpl.java 25 Jun 2003 19:55:46 -0000 1.28
@@ -77,8 +77,11 @@
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.URIResolver;
+import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
+import org.apache.xalan.xsltc.runtime.AbstractTranslet;
+import org.apache.xalan.xsltc.runtime.Hashtable;
public final class TemplatesImpl implements Templates, Serializable {
@@ -114,6 +117,11 @@
private int _transletIndex = -1;
/**
+ * Contains the list of auxiliary class definitions.
+ */
+ private Hashtable _auxClasses = null;
+
+ /**
* Output properties of this translet.
*/
private Properties _outputProperties;
@@ -129,6 +137,14 @@
private URIResolver _uriResolver = null;
/**
+ * Cache the DTM for the stylesheet in a thread local variable,
+ * which is used by the document('') function.
+ * Use ThreadLocal because a DTM cannot be shared between
+ * multiple threads.
+ */
+ private ThreadLocal _sdom = new ThreadLocal();
+
+ /**
* A reference to the transformer factory that this templates
* object belongs to.
*/
@@ -287,6 +303,10 @@
final int classCount = _bytecodes.length;
_class = new Class[classCount];
+ if (classCount > 1) {
+ _auxClasses = new Hashtable();
+ }
+
for (int i = 0; i < classCount; i++) {
_class[i] = loader.defineClass(_bytecodes[i]);
final Class superClass = _class[i].getSuperclass();
@@ -295,6 +315,9 @@
if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
_transletIndex = i;
}
+ else {
+ _auxClasses.put(_class[i].getName(), _class[i]);
+ }
}
if (_transletIndex < 0) {
@@ -326,13 +349,12 @@
// The translet needs to keep a reference to all its auxiliary
// class to prevent the GC from collecting them
- Translet translet = (Translet) _class[_transletIndex].newInstance();
- final int classCount = _class.length;
- for (int i = 0; i < classCount; i++) {
- if (i != _transletIndex) {
- translet.addAuxiliaryClass(_class[i]);
- }
+ AbstractTranslet translet = (AbstractTranslet)
_class[_transletIndex].newInstance();
+ translet.setTemplates(this);
+ if (_auxClasses != null) {
+ translet.setAuxiliaryClasses(_auxClasses);
}
+
return translet;
}
catch (InstantiationException e) {
@@ -379,5 +401,17 @@
}
}
+ /**
+ * Return the thread local copy of the stylesheet DOM.
+ */
+ public DOM getStylesheetDOM() {
+ return (DOM)_sdom.get();
+ }
+
+ /**
+ * Set the thread local copy of the stylesheet DOM.
+ */
+ public void setStylesheetDOM(DOM sdom) {
+ _sdom.set(sdom);
+ }
}
-
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]