/* * #! * Ontopia Navigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * 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 net.ontopia.utils.ontojsp; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.BodyContent; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.tagext.TagSupport; import net.ontopia.utils.OntopiaRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * INTERNAL: A class that executes a jsp page from a given root node. */ public class JSPPageExecuter { // initialize logging facility static Logger logger = LoggerFactory.getLogger(JSPPageExecuter.class.getName()); // members protected PageContext pageContext; /** * Default constructor. */ public JSPPageExecuter() { //! indentLevel = 0; } /** * Runs a JSP page (resp. function), represented by the specified * root node. It must get the corresponding page context object. The * <code>parentTag</code> is supposed to be null in a standalone * page (like a testcase) or given by the tag which calls this * function (inside the parent JSP). */ public void run(PageContext page, TagSupport parentTag, JSPTreeNodeIF root) throws JspException, IOException { pageContext = page; runTag(parentTag, root.makeClone()); } // --------------------------------------------------------- // internal helper methods // --------------------------------------------------------- /** * Executes the children of this node. */ protected void runTag(TagSupport parentTag, JSPTreeNodeIF node) throws JspException, IOException { //System.out.println("Running: " + node); List<JSPTreeNodeIF> children = node.getChildren(); for (JSPTreeNodeIF curNode : children) { TagSupport curTag = curNode.getTag(); // if content tag just put it out and proceed with next if (curTag == null) { pageContext.getOut().write(curNode.getContent()); continue; } // initialize tag //! curTag.setParent(node.getTag()); curTag.setParent(parentTag); curTag.setPageContext(pageContext); setAttributeValues(curNode, curTag); // run tag int startTagToken = curTag.doStartTag(); if (startTagToken != TagSupport.SKIP_BODY) { if (startTagToken == BodyTagSupport.EVAL_BODY_BUFFERED) { // check if BodyTagSupport instance BodyTagSupport btag = (BodyTagSupport) curTag; BodyContent body = pageContext.pushBody(); body.clearBody(); // TOMCAT MADE ME DO IT :-( btag.setBodyContent(body); btag.doInitBody(); loopTag(btag, curNode); // Release the body pageContext.popBody(); } else if (startTagToken == BodyTagSupport.EVAL_BODY_INCLUDE) { loopTag(curTag, curNode); } else { throw new OntopiaRuntimeException("Internal error: unknown doStartTag token: " + startTagToken); } } // FIXME: Handle SKIP_PAGE; curTag.doEndTag(); //tag.release(); FIXME: having this call here can't possibly be correct } // for i } private void loopTag(TagSupport tag, JSPTreeNodeIF curNode) throws JspException, IOException { // loop as long as tag says so int token; do { runTag(tag, curNode); token = tag.doAfterBody(); } while (token == BodyTagSupport.EVAL_BODY_AGAIN); if (token != BodyTagSupport.SKIP_BODY) throw new OntopiaRuntimeException("Internal error: unknown doAfterBody token: " + token); } /** * Initializes a tag by setting its attribute values. This assumes * it already has its parent and pageContext. */ private void setAttributeValues(JSPTreeNodeIF node, TagSupport tag) throws JspException { Map values = node.getAttributes(); Class tagclass = tag.getClass(); // Set attributes Iterator it = values.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); String command = "set" + Character.toUpperCase(key.charAt(0)) + key.substring(1); Class[] strparam = { String.class }; Class[] objparam = { Object.class }; Object[] params = { values.get(key) }; // get setter method Method setter = null; try { setter = tagclass.getMethod(command, strparam); } catch (NoSuchMethodException e) { try { setter = tagclass.getMethod(command, objparam); } catch (NoSuchMethodException e2) { throw new JspException(e2); } } // invoke setter method try { setter.invoke(tag, params); } catch (IllegalAccessException e) { throw new JspException(e); } catch (InvocationTargetException e) { Throwable cause = e.getCause(); throw new JspException(cause.getMessage(), cause); } } } }