Index: org/apache/commons/jelly/impl/TagScript.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/jelly/src/java/org/apache/commons/jelly/impl/TagScript.java,v retrieving revision 1.44 diff -u -r1.44 TagScript.java --- org/apache/commons/jelly/impl/TagScript.java 16 Sep 2004 01:12:11 -0000 1.44 +++ org/apache/commons/jelly/impl/TagScript.java 26 Sep 2004 23:45:22 -0000 @@ -128,7 +128,7 @@ public TagScript(TagFactory tagFactory) { this.tagFactory = tagFactory; } - + public String toString() { return super.toString() + "[tag=" + elementName + ";at=" + lineNumber + ":" + columnNumber + "]"; } @@ -503,8 +503,11 @@ Tag parentTag = null; if ( parent != null ) { parentTag = parent.getTag(); + tag.setParent( new WeakReferenceWrapperTag(parentTag) ); + } else { + tag.setParent(null); } - tag.setParent( parentTag ); + tag.setBody( tagBody ); if (tag instanceof NamespaceAwareTag) { Index: org/apache/commons/jelly/parser/XMLParser.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/jelly/src/java/org/apache/commons/jelly/parser/XMLParser.java,v retrieving revision 1.57 diff -u -r1.57 XMLParser.java --- org/apache/commons/jelly/parser/XMLParser.java 9 Sep 2004 15:10:04 -0000 1.57 +++ org/apache/commons/jelly/parser/XMLParser.java 26 Sep 2004 23:45:23 -0000 @@ -45,6 +45,7 @@ import org.apache.commons.jelly.impl.TagFactory; import org.apache.commons.jelly.impl.TagScript; import org.apache.commons.jelly.impl.TextScript; +import org.apache.commons.jelly.impl.WeakReferenceWrapperTagScript; import org.apache.commons.jelly.util.ClassLoaderUtils; import org.apache.commons.jelly.expression.CompositeExpression; import org.apache.commons.jelly.expression.ConstantExpression; @@ -1089,7 +1090,11 @@ */ protected void configureTagScript(TagScript aTagScript) { // set parent relationship... - aTagScript.setParent(this.tagScript); + if (this.tagScript == null) { + aTagScript.setParent(null); + } else { + aTagScript.setParent(new WeakReferenceWrapperTagScript(this.tagScript)); + } // set the namespace Map if ( elementNamespaces != null ) { Index: org/apache/commons/jelly/impl/WeakReferenceWrapperScript.java =================================================================== RCS file: org/apache/commons/jelly/impl/WeakReferenceWrapperScript.java diff -N org/apache/commons/jelly/impl/WeakReferenceWrapperScript.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ org/apache/commons/jelly/impl/WeakReferenceWrapperScript.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,60 @@ +/* + * Created on Sep 19, 2004 + * + */ +package org.apache.commons.jelly.impl; + +import java.lang.ref.WeakReference; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.JellyException; +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.XMLOutput; + +/** Wraps another Script instance in a WeakReference. Used to prevent + * a Tag class from holding a hard reference to its body script. + *

+ * If the underlying Script has been GC'd and is no longer available, + * an exception is thrown on any attempt to use this Script. + * + * @author Hans Gilde + * + */ +public class WeakReferenceWrapperScript implements Script { + private WeakReference reference; + + public WeakReferenceWrapperScript(Script script) { + reference = new WeakReference(script); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Script#compile() + */ + public Script compile() throws JellyException { + return script().compile(); + } + + /** + * @throws JellyException + */ + private Script script() throws JellyTagException { + Script script = (Script) reference.get(); + + if (script == null) { + throw new JellyTagException("Attempt to use a script that has been garbage collected."); + } + + return script; + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Script#run(org.apache.commons.jelly.JellyContext, org.apache.commons.jelly.XMLOutput) + */ + public void run(JellyContext context, XMLOutput output) + throws JellyTagException { + + script().run(context, output); + } + +} Index: org/apache/commons/jelly/impl/WeakReferenceWrapperTag.java =================================================================== RCS file: org/apache/commons/jelly/impl/WeakReferenceWrapperTag.java diff -N org/apache/commons/jelly/impl/WeakReferenceWrapperTag.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ org/apache/commons/jelly/impl/WeakReferenceWrapperTag.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,88 @@ +/* + * Created on Sep 19, 2004 + * + */ +package org.apache.commons.jelly.impl; + +import java.lang.ref.WeakReference; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.MissingAttributeException; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.Tag; +import org.apache.commons.jelly.XMLOutput; + +/** + * @author Hans Gilde + * + */ +public class WeakReferenceWrapperTag implements Tag { + private WeakReference reference; + + public WeakReferenceWrapperTag(Tag tag) { + reference = new WeakReference(tag); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#getParent() + */ + public Tag getParent() { + return tag().getParent(); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#setParent(org.apache.commons.jelly.Tag) + */ + public void setParent(Tag parent) { + tag().setParent(parent); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#getBody() + */ + public Script getBody() { + return tag().getBody(); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#setBody(org.apache.commons.jelly.Script) + */ + public void setBody(Script body) { + tag().setBody(body); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#getContext() + */ + public JellyContext getContext() { + return tag().getContext(); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#setContext(org.apache.commons.jelly.JellyContext) + */ + public void setContext(JellyContext context) throws JellyTagException { + tag().setContext(context); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#doTag(org.apache.commons.jelly.XMLOutput) + */ + public void doTag(XMLOutput output) throws MissingAttributeException, + JellyTagException { + tag().doTag(output); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.Tag#invokeBody(org.apache.commons.jelly.XMLOutput) + */ + public void invokeBody(XMLOutput output) throws JellyTagException { + tag().invokeBody(output); + } + + private Tag tag() { + return (Tag) reference.get(); + } + +} Index: org/apache/commons/jelly/impl/WeakReferenceWrapperTagScript.java =================================================================== RCS file: org/apache/commons/jelly/impl/WeakReferenceWrapperTagScript.java diff -N org/apache/commons/jelly/impl/WeakReferenceWrapperTagScript.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ org/apache/commons/jelly/impl/WeakReferenceWrapperTagScript.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,345 @@ +/* + * Created on Sep 26, 2004 + * + */ +package org.apache.commons.jelly.impl; + +import java.lang.ref.WeakReference; +import java.util.Map; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.JellyException; +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.LocationAware; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.Tag; +import org.apache.commons.jelly.XMLOutput; +import org.apache.commons.jelly.expression.Expression; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +/** + * @author Hans Gilde + * + */ +public class WeakReferenceWrapperTagScript extends TagScript { + private static final Log log = LogFactory.getLog(WeakReferenceWrapperTagScript.class); + + private WeakReference wrapper; + + public WeakReferenceWrapperTagScript(TagScript wrapped) { + wrapper = new WeakReference(wrapped); + } + + protected TagScript tagScript() { + return (TagScript) wrapper.get(); + } + + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#addAttribute(java.lang.String, org.apache.commons.jelly.expression.Expression) + */ + public void addAttribute(String name, Expression expression) { + tagScript().addAttribute(name, expression); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#applyLocation(org.apache.commons.jelly.LocationAware) + */ + protected void applyLocation(LocationAware locationAware) { + tagScript().applyLocation(locationAware); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#clearTag() + */ + protected void clearTag() { + + tagScript().clearTag(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.Script#compile() + */ + public Script compile() throws JellyException { + + return tagScript().compile(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#configureTag(org.apache.commons.jelly.Tag) + */ + protected void configureTag(Tag tag) throws JellyException { + + tagScript().configureTag(tag); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#convertType(java.lang.Object, java.lang.Class) + */ + protected Object convertType(Object value, Class requiredType) + throws JellyException { + + return tagScript().convertType(value, requiredType); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#createJellyException(java.lang.String, java.lang.Exception) + */ + protected JellyException createJellyException(String reason, Exception cause) { + + return tagScript().createJellyException(reason, cause); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#createJellyException(java.lang.String) + */ + protected JellyException createJellyException(String reason) { + + return tagScript().createJellyException(reason); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#createTag() + */ + protected Tag createTag() throws JellyException { + + return tagScript().createTag(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#endNamespacePrefixes(org.apache.commons.jelly.XMLOutput) + */ + protected void endNamespacePrefixes(XMLOutput output) throws SAXException { + + tagScript().endNamespacePrefixes(output); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getColumnNumber() + */ + public int getColumnNumber() { + + return tagScript().getColumnNumber(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getElementName() + */ + public String getElementName() { + + return tagScript().getElementName(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getFileName() + */ + public String getFileName() { + + return tagScript().getFileName(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getLineNumber() + */ + public int getLineNumber() { + + return tagScript().getLineNumber(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getLocalName() + */ + public String getLocalName() { + + return tagScript().getLocalName(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getNamespaceContext() + */ + public synchronized Map getNamespaceContext() { + + return tagScript().getNamespaceContext(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getParent() + */ + public TagScript getParent() { + + return tagScript().getParent(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getSaxAttributes() + */ + public Attributes getSaxAttributes() { + + return tagScript().getSaxAttributes(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getTag() + */ + public Tag getTag() throws JellyException { + + return tagScript().getTag(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getTagBody() + */ + public Script getTagBody() { + + return tagScript().getTagBody(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#getTagFactory() + */ + public TagFactory getTagFactory() { + + return tagScript().getTagFactory(); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#handleException(java.lang.Error) + */ + protected void handleException(Error e) throws Error, JellyTagException { + + tagScript().handleException(e); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#handleException(java.lang.Exception) + */ + protected void handleException(Exception e) throws JellyTagException { + + tagScript().handleException(e); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#handleException(org.apache.commons.jelly.JellyException) + */ + protected void handleException(JellyException e) throws JellyTagException { + + tagScript().handleException(e); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#handleException(org.apache.commons.jelly.JellyTagException) + */ + protected void handleException(JellyTagException e) + throws JellyTagException { + + tagScript().handleException(e); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.Script#run(org.apache.commons.jelly.JellyContext, org.apache.commons.jelly.XMLOutput) + */ + public void run(JellyContext context, XMLOutput output) + throws JellyTagException { + + tagScript().run(context, output); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setColumnNumber(int) + */ + public void setColumnNumber(int columnNumber) { + + tagScript().setColumnNumber(columnNumber); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setContextURLs(org.apache.commons.jelly.JellyContext) + */ + protected void setContextURLs(JellyContext context) + throws JellyTagException { + + tagScript().setContextURLs(context); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setElementName(java.lang.String) + */ + public void setElementName(String elementName) { + + tagScript().setElementName(elementName); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setFileName(java.lang.String) + */ + public void setFileName(String fileName) { + + tagScript().setFileName(fileName); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setLineNumber(int) + */ + public void setLineNumber(int lineNumber) { + + tagScript().setLineNumber(lineNumber); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setLocalName(java.lang.String) + */ + public void setLocalName(String localName) { + + tagScript().setLocalName(localName); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setLocator(org.xml.sax.Locator) + */ + public void setLocator(Locator locator) { + + tagScript().setLocator(locator); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setParent(org.apache.commons.jelly.impl.TagScript) + */ + public void setParent(TagScript parent) { + + tagScript().setParent(parent); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setSaxAttributes(org.xml.sax.Attributes) + */ + public void setSaxAttributes(Attributes saxAttributes) { + + tagScript().setSaxAttributes(saxAttributes); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setTag(org.apache.commons.jelly.Tag) + */ + protected void setTag(Tag tag) { + + tagScript().setTag(tag); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setTagBody(org.apache.commons.jelly.Script) + */ + public void setTagBody(Script tagBody) { + + tagScript().setTagBody(tagBody); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setTagFactory(org.apache.commons.jelly.impl.TagFactory) + */ + public void setTagFactory(TagFactory tagFactory) { + + tagScript().setTagFactory(tagFactory); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#setTagNamespacesMap(java.util.Map) + */ + public void setTagNamespacesMap(Map tagNamespacesMap) { + + tagScript().setTagNamespacesMap(tagNamespacesMap); + } + /* (non-Javadoc) + * @see org.apache.commons.jelly.impl.TagScript#startNamespacePrefixes(org.apache.commons.jelly.XMLOutput) + */ + protected void startNamespacePrefixes(XMLOutput output) throws SAXException { + + tagScript().startNamespacePrefixes(output); + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + + return tagScript().toString(); + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + + return tagScript().hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + + return tagScript().equals(obj); + } +}