Index: org/apache/commons/jelly/TagSupport.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/jelly/src/java/org/apache/commons/jelly/TagSupport.java,v retrieving revision 1.33 diff -u -r1.33 TagSupport.java --- org/apache/commons/jelly/TagSupport.java 9 Sep 2004 12:25:40 -0000 1.33 +++ org/apache/commons/jelly/TagSupport.java 13 Oct 2004 04:25:00 -0000 @@ -19,11 +19,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; -import java.util.List; -import org.apache.commons.jelly.impl.CompositeTextScriptBlock; -import org.apache.commons.jelly.impl.ScriptBlock; -import org.apache.commons.jelly.impl.TextScript; +import org.apache.commons.jelly.util.TagUtils; /**

TagSupport an abstract base class which is useful to * inherit from if developing your own tag.

@@ -242,55 +239,10 @@ /** * Find all text nodes inside the top level of this body and * if they are just whitespace then remove them + * @throws JellyTagException */ protected void trimBody() { - synchronized(body) { - // #### should refactor this code into - // #### trimWhitespace() methods on the Script objects - - if ( body instanceof CompositeTextScriptBlock ) { - CompositeTextScriptBlock block = (CompositeTextScriptBlock) body; - List list = block.getScriptList(); - int size = list.size(); - if ( size > 0 ) { - Script script = (Script) list.get(0); - if ( script instanceof TextScript ) { - TextScript textScript = (TextScript) script; - textScript.trimStartWhitespace(); - } - if ( size > 1 ) { - script = (Script) list.get(size - 1); - if ( script instanceof TextScript ) { - TextScript textScript = (TextScript) script; - textScript.trimEndWhitespace(); - } - } - } - } - else - if ( body instanceof ScriptBlock ) { - ScriptBlock block = (ScriptBlock) body; - List list = block.getScriptList(); - for ( int i = list.size() - 1; i >= 0; i-- ) { - Script script = (Script) list.get(i); - if ( script instanceof TextScript ) { - TextScript textScript = (TextScript) script; - String text = textScript.getText(); - text = text.trim(); - if ( text.length() == 0 ) { - list.remove(i); - } - else { - textScript.setText(text); - } - } - } - } - else if ( body instanceof TextScript ) { - TextScript textScript = (TextScript) body; - textScript.trimWhitespace(); - } - } + TagUtils.trimScript(body); } /** 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 13 Oct 2004 04:25:01 -0000 @@ -505,7 +505,8 @@ parentTag = parent.getTag(); } tag.setParent( parentTag ); - tag.setBody( tagBody ); + tag.setBody( new WeakReferenceWrapperScript(tagBody) ); + //tag.setBody( tagBody ); if (tag instanceof NamespaceAwareTag) { NamespaceAwareTag naTag = (NamespaceAwareTag) tag; 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,163 @@ +/* + * Copyright 2002,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jelly.impl; + +import java.lang.ref.WeakReference; +import java.util.Iterator; +import java.util.List; + +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.Tag; +import org.apache.commons.jelly.XMLOutput; +import org.apache.commons.jelly.tags.xml.ParamTag; +import org.apache.commons.jelly.util.TagUtils; + +/** 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. + *

+ * WARNING: This class is not a permanent part of the API and will be removed or replaced in a future release. + * Don't extend it or use it unless you absolutely must. + * + * @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(); + } + + /** Use this method to access the script. + * @throws JellyException If the script has been GC'd. + */ + protected 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); + } + + /**Trims the white space from the script and its children. + * TODO this code should be refactored into a formal part of the Script interface. + */ + public void trimWhitespace() throws JellyTagException { + TagUtils.trimScript(script()); + } + + /** Determines if this script (the one in the WeakReference) + * or a child reference contains a Script + * that's of a particular class. + *

+ * This method is in place + * to support specific features in the XML tag library and + * shouldn't be used by anyone at all. + * This method will be removed in a near-future verison of jelly. + *

+ * This method will be removed in a near-future verison of jelly. + * XXX this is totally bogus and temporary, we should not need to check the type of scripts. + * @param clazz Find a script that's an instance of this classs. + * @throws JellyTagException + */ + public boolean containsScriptType(Class clazz) throws JellyTagException { + Object bodyScript = script(); + + if (clazz.isInstance(bodyScript)) { + return true; + } + + if (bodyScript instanceof ScriptBlock) { + ScriptBlock scriptBlock = (ScriptBlock) bodyScript; + List scriptList = scriptBlock.getScriptList(); + for (Iterator iter = scriptList.iterator(); iter.hasNext(); ) { + Script script = (Script) iter.next(); + if (script instanceof StaticTagScript) { + return true; + } + } + } + + return false; + } + + /** Locates all child TagScripts, whose tags are of the type + * given. These tags are executed with the provided JellyContext and output. + *

+ * This method is in place + * to support specific features in the XML tag library and + * shouldn't be used by anyone at all. + * This method will be removed in a near-future verison of jelly. + *

+ * + * XXX if possible, this is actually more bogus than "containsScriptType", it must be removed ASAP + * + * @param clazz Execute all child tags of this type + * @param output The output to use when executing the tags. + * @throws JellyTagException + */ + public void invokeNestedTagsOfType(Class clazz, JellyContext context, XMLOutput output) throws JellyTagException { + Object bodyScript = script(); + + if (bodyScript instanceof ScriptBlock) { + ScriptBlock scriptBlock = (ScriptBlock) bodyScript; + List scriptList = scriptBlock.getScriptList(); + for (Iterator iter = scriptList.iterator(); iter.hasNext(); ) { + Script script = (Script) iter.next(); + if (script instanceof TagScript) { + + Tag tag = null; + try { + tag = ((TagScript) script).getTag(); + } catch (JellyException e) { + throw new JellyTagException(e); + } + + if (tag instanceof ParamTag) { + script.run(context, output); + } + + + } + } + } + } + +} Index: org/apache/commons/jelly/util/TagUtils.java =================================================================== RCS file: org/apache/commons/jelly/util/TagUtils.java diff -N org/apache/commons/jelly/util/TagUtils.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ org/apache/commons/jelly/util/TagUtils.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,97 @@ +/* + * Copyright 2002,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jelly.util; + +import java.util.List; + +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.impl.CompositeTextScriptBlock; +import org.apache.commons.jelly.impl.ScriptBlock; +import org.apache.commons.jelly.impl.TextScript; +import org.apache.commons.jelly.impl.WeakReferenceWrapperScript; + +/** Contains static methods to help tag developers. + * @author Hans Gilde + * + */ +public class TagUtils { + private TagUtils() { + + } + + /** Trims the whitespace from a script and its children. + * + */ + public static void trimScript(Script body) { + synchronized(body) { + // #### should refactor this code into + // #### trimWhitespace() methods on the Script objects + + if (body instanceof WeakReferenceWrapperScript) { + WeakReferenceWrapperScript wrrs = (WeakReferenceWrapperScript) body; + try { + wrrs.trimWhitespace(); + } catch (JellyTagException e) { + //TODO handle this exception once the Tag interface allows JellyTagException to be thrown + return; + } + } else if ( body instanceof CompositeTextScriptBlock ) { + CompositeTextScriptBlock block = (CompositeTextScriptBlock) body; + List list = block.getScriptList(); + int size = list.size(); + if ( size > 0 ) { + Script script = (Script) list.get(0); + if ( script instanceof TextScript ) { + TextScript textScript = (TextScript) script; + textScript.trimStartWhitespace(); + } + if ( size > 1 ) { + script = (Script) list.get(size - 1); + if ( script instanceof TextScript ) { + TextScript textScript = (TextScript) script; + textScript.trimEndWhitespace(); + } + } + } + } + else + if ( body instanceof ScriptBlock ) { + ScriptBlock block = (ScriptBlock) body; + List list = block.getScriptList(); + for ( int i = list.size() - 1; i >= 0; i-- ) { + Script script = (Script) list.get(i); + if ( script instanceof TextScript ) { + TextScript textScript = (TextScript) script; + String text = textScript.getText(); + text = text.trim(); + if ( text.length() == 0 ) { + list.remove(i); + } + else { + textScript.setText(text); + } + } + } + } + else if ( body instanceof TextScript ) { + TextScript textScript = (TextScript) body; + textScript.trimWhitespace(); + } + } + } + +}