/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.cocoon.taglib; import java.util.Map; import java.io.IOException; import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.environment.Context; import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Session; import org.apache.cocoon.environment.SourceResolver; import org.xml.sax.Attributes; import org.xml.sax.SAXException; /** * Abstract implementation for all Tags * * @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a> * @version CVS $Id$ */ public abstract class TagSupport extends AbstractLogEnabled implements Tag, Recyclable { protected Tag parent; protected SourceResolver resolver; protected Map objectModel; protected Parameters parameters; private Request request; /** * Find the instance of a given class type that is closest to a given * instance. * This method uses the getParent method from the Tag * interface. * This method is used for coordination among cooperating tags. * * @param from The instance from where to start looking. * @param klass The subclass of Tag or interface to be matched * @return the nearest ancestor that implements the interface * or is an instance of the class specified */ public static final Tag findAncestorWithClass(Tag from, Class klass) { boolean isInterface = false; if (from == null || klass == null || (!Tag.class.isAssignableFrom(klass) && !(isInterface = klass.isInterface()))) { return null; } for (;;) { Tag tag = from.getParent(); if (tag == null) { return null; } if ((isInterface && klass.isInstance(tag)) || klass.isAssignableFrom(tag.getClass())) { return tag; } from = tag; } } /** * Process the end tag for this instance. * * @return EVAL_PAGE. * @throws SAXException */ public int doEndTag(String namespaceURI, String localName, String qName) throws SAXException { return EVAL_PAGE; } /** * Process the start tag for this instance. * <p> * The doStartTag method assumes that pageContext and * parent have been set. It also assumes that any properties exposed as * attributes have been set too. When this method is invoked, the body * has not yet been evaluated. * * @return EVAL_BODY or SKIP_BODY. */ public int doStartTag(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { return EVAL_BODY; } /** * Searches for the named attribute in request, session (if valid), * and application scope(s) in order and returns the value associated or * null. * * @return the value associated or null */ public final Object findAttribute(String name) { if (request == null) request = ObjectModelHelper.getRequest(objectModel); Object o = request.getAttribute(name); if (o != null) return o; Session session = request.getSession(false); if (session != null) { o = session.getAttribute(name); if (o != null) return o; } Context context = ObjectModelHelper.getContext(objectModel); return context.getAttribute(name); } /** * Get the parent (closest enclosing tag handler) for this tag handler. * * @return the current parent, or null if none. */ public final Tag getParent() { return parent; } public void recycle() { getLogger().debug("recycle"); this.parent = null; this.resolver = null; this.objectModel = null; this.parameters = null; this.request = null; } /** * Set the parent (closest enclosing tag handler) of this tag handler. * Invoked by the TagTransformer prior to doStartTag(). * <p> * This value is *not* reset by doEndTag() and must be explicitly reset * by a Tag implementation. * * @param parent the parent tag, or null. */ public final void setParent(Tag parent) { this.parent = parent; } /** * Set the <code>SourceResolver</code>, objectModel <code>Map</code> * and sitemap <code>Parameters</code> used to process the request. */ public void setup(SourceResolver resolver, Map objectModel, Parameters parameters) throws SAXException, IOException { this.resolver = resolver; this.objectModel = objectModel; this.parameters = parameters; } }