001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.taglib;
018:
019: import java.util.Map;
020: import java.io.IOException;
021:
022: import org.apache.avalon.excalibur.pool.Recyclable;
023: import org.apache.avalon.framework.logger.AbstractLogEnabled;
024: import org.apache.avalon.framework.parameters.Parameters;
025: import org.apache.cocoon.environment.Context;
026: import org.apache.cocoon.environment.ObjectModelHelper;
027: import org.apache.cocoon.environment.Request;
028: import org.apache.cocoon.environment.Session;
029: import org.apache.cocoon.environment.SourceResolver;
030:
031: import org.xml.sax.Attributes;
032: import org.xml.sax.SAXException;
033:
034: /**
035: * Abstract implementation for all Tags
036: *
037: * @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
038: * @version CVS $Id: TagSupport.java 433543 2006-08-22 06:22:54Z crossley $
039: */
040: public abstract class TagSupport extends AbstractLogEnabled implements
041: Tag, Recyclable {
042: protected Tag parent;
043: protected SourceResolver resolver;
044: protected Map objectModel;
045: protected Parameters parameters;
046: private Request request;
047:
048: /**
049: * Find the instance of a given class type that is closest to a given
050: * instance.
051: * This method uses the getParent method from the Tag
052: * interface.
053: * This method is used for coordination among cooperating tags.
054: *
055: * @param from The instance from where to start looking.
056: * @param klass The subclass of Tag or interface to be matched
057: * @return the nearest ancestor that implements the interface
058: * or is an instance of the class specified
059: */
060: public static final Tag findAncestorWithClass(Tag from, Class klass) {
061: boolean isInterface = false;
062:
063: if (from == null
064: || klass == null
065: || (!Tag.class.isAssignableFrom(klass) && !(isInterface = klass
066: .isInterface()))) {
067: return null;
068: }
069:
070: for (;;) {
071: Tag tag = from.getParent();
072:
073: if (tag == null) {
074: return null;
075: }
076:
077: if ((isInterface && klass.isInstance(tag))
078: || klass.isAssignableFrom(tag.getClass())) {
079: return tag;
080: }
081: from = tag;
082: }
083: }
084:
085: /**
086: * Process the end tag for this instance.
087: *
088: * @return EVAL_PAGE.
089: * @throws SAXException
090: */
091: public int doEndTag(String namespaceURI, String localName,
092: String qName) throws SAXException {
093: return EVAL_PAGE;
094: }
095:
096: /**
097: * Process the start tag for this instance.
098: * <p>
099: * The doStartTag method assumes that pageContext and
100: * parent have been set. It also assumes that any properties exposed as
101: * attributes have been set too. When this method is invoked, the body
102: * has not yet been evaluated.
103: *
104: * @return EVAL_BODY or SKIP_BODY.
105: */
106: public int doStartTag(String namespaceURI, String localName,
107: String qName, Attributes atts) throws SAXException {
108: return EVAL_BODY;
109: }
110:
111: /**
112: * Searches for the named attribute in request, session (if valid),
113: * and application scope(s) in order and returns the value associated or
114: * null.
115: *
116: * @return the value associated or null
117: */
118: public final Object findAttribute(String name) {
119: if (request == null)
120: request = ObjectModelHelper.getRequest(objectModel);
121: Object o = request.getAttribute(name);
122: if (o != null)
123: return o;
124:
125: Session session = request.getSession(false);
126: if (session != null) {
127: o = session.getAttribute(name);
128: if (o != null)
129: return o;
130: }
131: Context context = ObjectModelHelper.getContext(objectModel);
132: return context.getAttribute(name);
133: }
134:
135: /**
136: * Get the parent (closest enclosing tag handler) for this tag handler.
137: *
138: * @return the current parent, or null if none.
139: */
140: public final Tag getParent() {
141: return parent;
142: }
143:
144: public void recycle() {
145: getLogger().debug("recycle");
146: this .parent = null;
147: this .resolver = null;
148: this .objectModel = null;
149: this .parameters = null;
150: this .request = null;
151: }
152:
153: /**
154: * Set the parent (closest enclosing tag handler) of this tag handler.
155: * Invoked by the TagTransformer prior to doStartTag().
156: * <p>
157: * This value is *not* reset by doEndTag() and must be explicitly reset
158: * by a Tag implementation.
159: *
160: * @param parent the parent tag, or null.
161: */
162: public final void setParent(Tag parent) {
163: this .parent = parent;
164: }
165:
166: /**
167: * Set the <code>SourceResolver</code>, objectModel <code>Map</code>
168: * and sitemap <code>Parameters</code> used to process the request.
169: */
170: public void setup(SourceResolver resolver, Map objectModel,
171: Parameters parameters) throws SAXException, IOException {
172: this.resolver = resolver;
173: this.objectModel = objectModel;
174: this.parameters = parameters;
175: }
176: }
|