jkesselm 00/10/25 08:06:31
Modified: java/src/org/apache/xalan/processor
CompiledStylesheetBundle.java CompiledTemplate.java
Log:
Better documentation of compiled stylesheet sketch
Revision Changes Path
1.2 +356 -236
xml-xalan/java/src/org/apache/xalan/processor/CompiledStylesheetBundle.java
Index: CompiledStylesheetBundle.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/processor/CompiledStylesheetBundle.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CompiledStylesheetBundle.java 2000/10/23 19:23:23 1.1
+++ CompiledStylesheetBundle.java 2000/10/25 15:06:28 1.2
@@ -93,296 +93,416 @@
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
-// Java Compiler support. *****
-// TODO: Merge the Microsoft VJ++ workarounds in this file into that one.
-import org.apache.xalan.utils.synthetic.JavaUtils;
-
/**
* <meta name="usage" content="advanced"/>
- * File save and reload for Compiled Stylesheets.
+ * Serialize and reload routines for Compiled Stylesheets. Basically, a
+ * "bundle" is a zipfile containing the generated and compiled java
+ * classes, plus a .ser (ObjectStream) representation of those classes
+ * as actually instantiated and connected to represent a top-level
+ * Stylesheet. This class provides routines that generate a bundle in
+ * a disk file, and that will reread a bundle from such a file.
+ *
* @see CompilingStylesheetHandler
*/
public class CompiledStylesheetBundle
{
+ /** Public constructor. The loadBundle() operation requires an actual
+ * compiledStylesheetBundle object, for reasons discussed there.
+ */
public CompiledStylesheetBundle()
{
}
- // Create an executable bundle -- a zipfile
- // containing the serialized root, the synthesized classes needed
- // to support it, and a main entry point which retrieves these.
- //
- // ***** ISSUE: Need to make sure we're looking in the same directory
- // that the classes were generated into. Currently that's ".". Should
- // be parameterized both during compilation and here.
- // ***** ISSUE: What filename to write to? Hardcoded for initial test,
- // should be taken from stylesheet's Public/System IDs. Stand-alone
- // loader entry point ditto?
- // ***** ISSUE: ZIP or JAR? Zipfile support is in Java 1.1.x, direct
- // jarfile doesn't appear until 1.2. Main difference is that latter
- // automatically produces manefest, but a manefest is optional anyway.
- static void createBundle(Stylesheet root,Vector compiledTemplates)
- {
- String outdir="."+File.separator;
- java.util.Hashtable dirs=new java.util.Hashtable();
+ /** Create an executable bundle -- a zipfile which contains
+ * the serialized Root Stylesheet and the synthesized classes needed
+ * to support it. Nominally this should be a jarfile, but zipfiles work
+ * and jarfile support wasn't added to the JDK until 1.2.
+ * <P>
+ * TODO: Open issues in CompiledStylesheetBundle.createBundle()
+ * <ul>
+ * <li> We need to copy classfiles from the directory that the code was
+ * generated into. Currently that's hardwired as "." -- but when we
+ * parameterize the code-gen operations we'll need to update this too.
+ * <li> What filename should we give the bundle, and where should we
+ * output it? Currently that's hardcoded, but it really should be
+ * parameterized and/or derived from the stylesheet's Public/System IDs.
+ * <li>Should we really be writing to a file, or should we be generating
+ * a stream which the caller directs appropriately?
+ * <li>Should we really be invoked as part of the compilation? Or are we
+ * in fact a "serialization" mechanism for compiled stylesheets?
+ * </ul>
+ *
+ * @param Stylesheet root The compiled Root Stylesheet, after being
+ * processed by CompilingStylesheetHandler's endDocument() method.
+ * @param Vector compiledTemplates A list of the Class objects that were
+ * generated to support this stylesheet. (Avoids rewalking the tree to
+ * gather than information.)
+ */
+ static void createBundle(Stylesheet root,Vector compiledTemplates)
+ {
+ //TODO: outdir should be parameterized
+ String outdir="."+File.separator;
- try {
- java.io.FileOutputStream f=
- new
java.io.FileOutputStream(outdir+"CompiledStylesheet.zip");
- java.util.zip.ZipOutputStream zf=new
java.util.zip.ZipOutputStream(f);
- zf.setMethod(zf.DEFLATED);
+ try
+ {
+ java.io.FileOutputStream f=
+ new
java.io.FileOutputStream(outdir+"CompiledStylesheet.zip");
+ java.util.zip.ZipOutputStream zf=new
java.util.zip.ZipOutputStream(f);
+ zf.setMethod(zf.DEFLATED);
- // Copy in the classfiles
- byte buffer[]=new byte[4096];
- java.util.zip.ZipEntry ze;
- for(int i=compiledTemplates.size()-1;i>=0;--i)
- {
- // WARNING: I'm assuming that a package name has been
specified,
- // which should be safe in this case. If that changes,
this
- // lazy parse needs to be improved.
- Class c=compiledTemplates.elementAt(i).getClass();
- String fullname=c.getName();
- int start=fullname.lastIndexOf(".");
- String packagename=fullname.substring(0,start);
- String shortname=fullname.substring(start+1);
- // Need to convert as a relative path for the jarfile;
- // it's "anchored" later when we open for read.
- String
source=packageNameToDirectory(packagename,outdir,File.separator)
- +shortname+".class";
- String sink=packageNameToDirectory(packagename,"","/")
- +shortname+".class";
-
-// I'm not sure whether this is needed or not. The JDK I'm using seems to say
-// it isn't, but I want to keep it around for now in case another JDK
-// disagrees.
-if(false)
-{
- for(int slash=sink.indexOf('/');
- slash>=0;
- slash=sink.indexOf('/',slash+1))
+ // Copy in the classfiles
+ byte buffer[]=new byte[4096];
+ java.util.zip.ZipEntry ze;
+ for(int i=compiledTemplates.size()-1;i>=0;--i)
{
- String dirname=sink.substring(0,slash+1);
- if(dirs.get(dirname) == null)
- {
- ze=new java.util.zip.ZipEntry(dirname);
- zf.putNextEntry(ze);
- zf.closeEntry();
- dirs.put(dirname,dirname);
- }
- }
-}
+ // WARNING: I'm assuming that a package name
has been specified,
+ // which should be safe in this case. If that
changes, this
+ // lazy parse needs to be improved.
+ Class
c=compiledTemplates.elementAt(i).getClass();
+ String fullname=c.getName();
+ int start=fullname.lastIndexOf(".");
+ String packagename=fullname.substring(0,start);
+ String shortname=fullname.substring(start+1);
+ // Where to copy the classfile from.
+ // TODO: Can we get the bytes direct from the
Class object???
+ String source=
+
packageNameToDirectory(packagename,outdir,File.separator)
+ +shortname+".class";
+ // Where to write the class within the
jar/zipfile's
+ // directory structure
+ String sink=
+
packageNameToDirectory(packagename,"","/")
+ +shortname+".class";
- ze=new java.util.zip.ZipEntry(sink);
- zf.putNextEntry(ze);
- java.io.FileInputStream fis=new
java.io.FileInputStream(source);
- int count=0;
- for(int got=1;got>=0;)
- {
- got=fis.read(buffer);
- if(got>0)
+ ze=new java.util.zip.ZipEntry(sink);
+ zf.putNextEntry(ze);
+ java.io.FileInputStream fis=new
java.io.FileInputStream(source);
+ // Need to count how many bytes are
transferred; the ZipEntry
+ // does _NOT_ set itself automatically.
+ int count=0;
+ for(int got=1;got>=0;)
{
- zf.write(buffer,0,got);
- count+=got;
+ got=fis.read(buffer);
+ if(got>0)
+ {
+ zf.write(buffer,0,got);
+ count+=got;
+ }
}
+ fis.close();
+ ze.setSize(count); // Should be set
automagically, but isn't.
+ zf.closeEntry();
}
- fis.close();
- ze.setSize(count); // Ought to get set automagically,
BUT....
- zf.closeEntry();
- }
- // Write out the serialized stylesheet
- ze=new java.util.zip.ZipEntry("Stylesheet.ser");
- zf.putNextEntry(ze);
- java.io.ObjectOutputStream of=new
java.io.ObjectOutputStream(zf);
- of.writeObject(root);
- of.flush(); // ***** Should this be close?
- zf.closeEntry();
+ // Write out the serialized stylesheet tree which uses
the classes
+ // we've just saved.
+ // TODO: Should this name be related to the stylesheet
name/filename?
+ ze=new java.util.zip.ZipEntry("Stylesheet.ser");
+ zf.putNextEntry(ze);
+ java.io.ObjectOutputStream of=new
java.io.ObjectOutputStream(zf);
+ of.writeObject(root);
+ of.flush();
+ zf.closeEntry();
- // TODO: *****MAKE SELF-LOADABLE!*****
- // Set up a Classloader pointed at the zipfile and deserialize
from?
+ // TODO: Should bundle be self-loadable (generated
entry point)?
- // This may be overkill, but I'm getting complaints about
- // "not a ZIP file (END header not found"...
- zf.finish();
- zf.flush();
- zf.close();
- f.flush();
- f.close();
- }
- catch(java.io.IOException e)
- {
- System.err.println("Exception while packaging compiled
stylesheet");
- e.printStackTrace(System.err);
- }
- }
+ // TODO: The following is undoubtedly massive overkill,
but I had
+ // problems with "not a ZIP file (END header not
found)"...
+ zf.finish();
+ zf.flush();
+ zf.close();
+ f.flush();
+ f.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // TODO: Improve bundling diagnostics
+ System.err.println("Exception while bundling compiled
stylesheet");
+ e.printStackTrace(System.err);
+ }
+ }
- // Reload an executable bundle -- a zipfile or jarfile
- // containing the serialized root, the synthesized classes needed
- // to support it, and a main entry point which retrieves these.
- //
- // Note use of a custom classloader in order to pick these up
interactively.
- public Stylesheet loadBundle(String filename)
- throws java.io.IOException,java.lang.ClassNotFoundException
- {
- Stylesheet ss=null;
-
- java.io.InputStream is;
- java.io.ObjectInputStream os;
- if(true)
+ /** Reload an executable bundle -- a zipfile or jarfile
+ * containing the serialized root and the synthesized classes needed
+ * to support it, and a main entry point which retrieves these.
+ * A custom classloader is used so we can pick these up interactively,
+ * along with a customized version of ObjectInputStream that can be told
+ * which classloader to consult.
+ * <p>
+ * TODO: Open issues in CompiledStylesheetBundle.loadBundle()
+ * <ul>
+ * <li>At the moment this is an instance method, because the support
+ * objects mentioned above are declared as inner classes. They're
arguably
+ * general enough to be worth factoring out...
+ * <li>Should this be restructured to be able to read from other kinds of
+ * streams? Would require significant changes to the classloader, to
preload
+ * it from the stream rather than having it access the zipfile on demand.
+ * </ul>
+ *
+ * @param String filename Filesystem name of the bundle file to be
loaded.
+ * @return Stylesheet as loaded.
+ * @exception java.io.IOException if there are any problems reading the
+ * bundle file
+ * @exception java.lang.ClassNotFoundException if a class used in
+ * serializing the Stylesheet can't be resolved. This could be a glitch
+ * in the bundle, but is more likely to be incompatable versions if the
+ * Xalan code was changed between when the bundle was created and when it
+ * is being reloaded.
+ */
+ public Stylesheet loadBundle(String filename)
+ throws java.io.IOException,java.lang.ClassNotFoundException
+ {
+ java.io.InputStream is=null;
+ java.io.ObjectInputStream os=null;
+ Stylesheet ss=null;
+
+ try
{
+ // Create the custom classloader which will consult the
bundle
java.lang.ClassLoader cl=new
ZipfileClassLoader(filename);
+ // Read the .ser file from the bundle, via that
classloader
is=cl.getResourceAsStream("Stylesheet.ser");
+ // Read objects from the .ser, loading from bundle if
necessary
os=new ClassLoaderObjectInputStream(cl,is);
+ ss=(Stylesheet)os.readObject();
}
- else
+ finally
{
-
is=this.getClass().getResourceAsStream("/Stylesheet.ser");
- os=new java.io.ObjectInputStream(is);
+ // Whether read succeeded or not, release the file
resources
+ if(os!=null) os.close();
+ if(is!=null) is.close();
}
-
- ss=(Stylesheet)os.readObject();
- os.close();
- is.close();
-
- return ss;
- }
-
+ return ss;
+ }
- static String packageNameToDirectory(String packagename,String
baseLocation,
+ /** Utility function: Take a dot-delimited packagename and a base
+ * directory, and return a relative directory suitable for locating
+ * .java and .class files.
+ * TODO: This should be moved somewhere more reusable,
+ * probably into the compiler-invocation support stuff or
synthetic.Class.
+ *
+ * @param String packagename dot-delimited packagename, as you'd write
it
+ * in the Java package statement.
+ * @param String baseLocation Base directory, appended to the front of
the
+ * returned value. We discard anything after the last instance of the
+ * separator, to allow passing in a filename ... but that means that if
+ * you want to pass in a directory, it's your responsibility to make
+ * sure it ends in the separator character.
+ * TODO: Clean up directory parsing a bit...
+ * @param String separator Separator into which the '.'s are converted.
+ * This is a parameter because I'm using this function to work with
+ * zipfiles (which insist on '/') as well as the normal filesystem
+ * (which varies from platform to platform).
+ */
+ static String packageNameToDirectory(String packagename,String
baseLocation,
String separator)
- {
- int fnstart=baseLocation.lastIndexOf(separator);
- StringBuffer subdir=new StringBuffer(
- (fnstart>=0)
- ? baseLocation.substring(0,fnstart+1)
- : "");
- StringTokenizer parts=
- new StringTokenizer(packagename,".");
- while(parts.hasMoreTokens())
- subdir.append(parts.nextToken()).append(separator);
- return subdir.toString();
- }
-
- // Custom classloader is needed if we want to load from a
- // zipfile which wasn't on the classpath at startup time.
- class ZipfileClassLoader extends ClassLoader
- {
- String filename;
- java.util.zip.ZipFile zip=null;
-
- ZipfileClassLoader(String filename) throws java.io.IOException
{
- this.filename=filename;
- zip=new java.util.zip.ZipFile(filename);
+ int fnstart=baseLocation.lastIndexOf(separator);
+ StringBuffer subdir=new StringBuffer(
+ (fnstart>=0)
+ ? baseLocation.substring(0,fnstart+1)
+ : "");
+ // Simple parse-and-reassemble loop
+ StringTokenizer parts=new StringTokenizer(packagename,".");
+ while(parts.hasMoreTokens())
+ subdir.append(parts.nextToken()).append(separator);
+ return subdir.toString();
}
+
+ //=================================================================
- // TODO: ***** RECONSIDER EFFECTIVE CLASSPATH
- // What I really want is to try system classes, than zipfile, then
- // user classpath. JDK 1.2 seems to have hooks that will support that,
- // but I'm not sure about JDK 1.1.
- public Class findClass(String name)
+ /** This is a quick-and-dirty classloader which effectively appends
+ * the specified zipfile to the tail end of the existing classpath
+ * (by consulting the ClassLoader which loaded _it_ first, and only
+ * then attempting to load from the file.)
+ * This allows us to read from files -- in particular, from
+ * CompiledStylesheetBundles -- which weren't available at the time the
+ * applications was launched.
+ * <p>
+ * TODO: BEHAVIOR IS INCOMPLETE; consider finishing it properly...
+ * TODO: This probably should be factored out as an independent object
+ * rather than an inner class. It's resuable.
+ * TODO: In Java 1.2.x, this can be replaced to a greater or lesser
extent
+ * by URIClassLoader.
+ */
+ class ZipfileClassLoader extends ClassLoader
{
- Class c=null;
- try
+ java.util.zip.ZipFile zip=null;
+
+ /** Constructor.
+ * TODO: Should we be able to load from stream as well as
string?
+ * That would require a preload solution or a random-access
stream...
+ * OK for our simple case where we know we're going to use
everything
+ * eventually, not so hot for others.
+ *
+ * @param String filename Name of the zipfile to be read
+ */
+ public ZipfileClassLoader(String filename) throws
java.io.IOException
{
- c=this.getClass().forName(name);
+ zip=new java.util.zip.ZipFile(filename);
}
- catch (ClassNotFoundException e)
+
+ /** Find a class within the Zipfile. Note that this does not
_resolve_
+ * the class, and hence should probably not be used by the
general public.
+ * TODO: Reconsider the resulting effective classpath.
+ * What I really want is to try system classes, than zipfile,
then
+ * user classpath. JDK 1.2 seems to have hooks that will support
that,
+ * but I'm not sure about JDK 1.1.
+ *
+ * @param String name fully-qualified classname (including
package, if any)
+ */
+ Class findClass(String name)
{
- byte[] b = loadClassData(name);
- if(b!=null)
- c=defineClass(name,b,0,b.length);
+ Class c=null;
+ try
+ {
+ c=this.getClass().forName(name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ byte[] b = loadClassData(name);
+ if(b!=null)
+ c=defineClass(name,b,0,b.length);
+ }
+ return c;
}
- return c;
- }
- private byte[] loadClassData(String name)
- {
- int start=name.lastIndexOf(".");
- String packagename=name.substring(0,start);
- String shortname=name.substring(start+1);
- // Need to convert as a relative path for the jarfile;
- // it's "anchored" later when we open for read.
- String fn=packageNameToDirectory(packagename,"","/")
+ /** Internal subroutine: Givne the name of a class (or of a
resource),
+ * access the zipfile and retrieve the contents thereof as a
byte array.
+ * TODO: Implement the "leading / means already in filename
syntax" trick?
+ * Or is that irrelevant?
+ *
+ * @param String name Name to be retrieved, in Java package
syntax.
+ * @return byte[] with full contents of "file".
+ */
+ private byte[] loadClassData(String name)
+ {
+ int start=name.lastIndexOf(".");
+ String packagename=name.substring(0,start);
+ String shortname=name.substring(start+1);
+ // Need to convert as a relative path for the jarfile;
+ // it's "anchored" later when we open for read.
+ String fn=packageNameToDirectory(packagename,"","/")
+shortname+".class";
- byte[] data=null;
- try
- {
- java.util.zip.ZipEntry entry=zip.getEntry(fn);
-
- // If it isn't in the zipfile, we can't retrieve any
data
- if(entry!=null)
+ byte[] data=null;
+ try
{
- // This assumes entry length fits in an int.
Should be safe.
- int bufsize = (int)entry.getSize();
- data=new byte[bufsize];
- java.io.InputStream
is=zip.getInputStream(entry);
- int len=0, off=0;
- while (off<bufsize){
- len = is.read(data,off,bufsize-off);
- off += len;
+ java.util.zip.ZipEntry entry=zip.getEntry(fn);
+
+ // If it isn't in the zipfile, we can't
retrieve any data
+ if(entry!=null)
+ {
+ // This assumes entry length fits in an
int. Should be safe.
+ int bufsize = (int)entry.getSize();
+ data=new byte[bufsize];
+ java.io.InputStream
is=zip.getInputStream(entry);
+ int len=0, off=0;
+ while (off<bufsize)
+ {
+ len =
is.read(data,off,bufsize-off);
+ off += len;
+ }
+ is.close();
}
- is.close();
}
+ catch(java.io.IOException e)
+ {
+ System.err.println("Exception while reloading
compiled stylesheet");
+ e.printStackTrace(System.err);
+ }
+ return data;
+ }
+
+ /** This is one of the main entry points that makes it a "real"
+ * classloader.
+ * @see java.io.ClassLoader.loadClass
+ */
+ public synchronized Class loadClass(String name, boolean
resolve)
+ throws ClassNotFoundException
+ {
+ Class c=findClass(name);
+ if(c!=null && resolve==true)
+ resolveClass(c);
+ return c;
}
- catch(java.io.IOException e)
+
+ /** This is one of the main entry points that makes it a "real"
+ * classloader.
+ * @see java.io.ClassLoader.getResourceAsStream
+ */
+ public java.io.InputStream getResourceAsStream(String name)
{
- System.err.println("Exception while reloading compiled
stylesheet");
- e.printStackTrace(System.err);
+ java.io.InputStream is=null;
+ try
+ {
+ java.util.zip.ZipEntry entry=zip.getEntry(name);
+ is=zip.getInputStream(entry);
+ }
+ catch(java.io.IOException e)
+ {
+ System.err.println("Problem loading compiled
stylesheet");
+ e.printStackTrace();
+ // TODO: ***** Should this fall back to default
classloader?
+ // is=this.getClass().getResourceAsStream(name);
+ }
+ return is;
}
- return data;
- }
+ }
+
+ //===============================================================
- public synchronized Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException
+ /** Modified ObjectInputStream which consults a specific ClassLoader
+ * rather than the default. This was required to allow reloading our
+ * CompiledStylesheetBundle files, which carry both a serialized
+ * object tree and the additional classfiles needed to support it.
+ * <p>
+ * An alternative solution would have been to put a stub object in
+ * the bundle file, explicitly load that (setting its default
+ * classloader in the process), then have it load the rest of the data,
+ * but that requires another generated class and I'm not convinced it's
+ * really cleaner.
+ * <p>
+ * TODO: Make this a more complete implementation (other factories, eg)?
+ * TODO: Move this to somewhere more reusable.
+ */
+ class ClassLoaderObjectInputStream extends java.io.ObjectInputStream
{
- Class c=findClass(name);
- if(c!=null && resolve==true)
- resolveClass(c);
- return c;
- }
+ java.lang.ClassLoader cl;
- public java.io.InputStream getResourceAsStream(String name)
- {
- java.io.InputStream is=null;
- try
+ /** Public constructor.
+ * @param java.lang.ClassLoader cl The custom classloader to be
used
+ * when deserializing these objects. Note that it is the
classloader's
+ * responsibility to deliver _all_ classes for this stream;
that will
+ * probably requre that it understand how to fall back upon a
parent
+ * or default classloader.
+ * @param java.io.InputStream is The stream from which to read
the
+ * serialized representation of the objects.
+ */
+ public ClassLoaderObjectInputStream(java.lang.ClassLoader
cl,java.io.InputStream is)
+ throws java.io.IOException
{
- java.util.zip.ZipEntry entry=zip.getEntry(name);
- is=zip.getInputStream(entry);
+ super(is);
+ this.cl=cl;
}
- catch(java.io.IOException e)
+
+ /** Overriding this routine is what allows us to consult the
specified
+ * classloader rather than the default. Note that this assumes
the
+ * classloader knows how to cascade to others as appropriate
(and with
+ * the proper priority of search), since it has to resolve
_all_
+ * classes that may be referenced in the object stream --
including
+ * system classes.
+ * <p>
+ * Should we have a "backup" fallback here? I'd say no;
+ * the user may want to distinguish whether the class came from
+ * the intended classloader, and it's easy enough to handle any
+ * fallbacks at that level.
+ */
+ protected Class resolveClass(java.io.ObjectStreamClass v)
+ throws java.io.IOException, ClassNotFoundException
{
- System.err.println("Problem loading compiled stylesheet");
- e.printStackTrace();
- // TODO: ***** Should this fall back to default classloader?
- // is=this.getClass().getResourceAsStream(name);
+ return cl.loadClass(v.getName());
}
- return is;
}
- }
- // Kluge: Check a specific classloader when deserializing. Alternative
- // is to dump a stub object into the zipfile and have it do the deserialize
- // ... which doesn't strike me as being any prettier.
- class ClassLoaderObjectInputStream extends java.io.ObjectInputStream
- {
- java.lang.ClassLoader cl;
- public ClassLoaderObjectInputStream(java.lang.ClassLoader
cl,java.io.InputStream is)
- throws java.io.IOException
- {
- super(is);
- this.cl=cl;
- }
-
- // Note that this assumes cl knows how to cascade to other classloaders
- // as appropriate, since it has to resolve _all_ classes that may be
- // referenced in the object stream -- including system classes.
- protected Class resolveClass(java.io.ObjectStreamClass v)
- throws java.io.IOException, ClassNotFoundException
- {
- return cl.loadClass(v.getName());
- }
- }
-
}
1.5 +57 -0
xml-xalan/java/src/org/apache/xalan/processor/CompiledTemplate.java
Index: CompiledTemplate.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/processor/CompiledTemplate.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- CompiledTemplate.java 2000/10/17 18:47:44 1.4
+++ CompiledTemplate.java 2000/10/25 15:06:29 1.5
@@ -1,3 +1,60 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
/** Abstract superclass for generated template classes produced
* by the CompilingStylesheetProcessor/CompilingStylesheetHandler.
* (This had been an interface, but I want to factor out some