Package ch.entwine.weblounge.taglib

Source Code of ch.entwine.weblounge.taglib.WebloungeTag

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.taglib;

import ch.entwine.weblounge.common.impl.request.RequestUtils;
import ch.entwine.weblounge.common.impl.request.WebloungeRequestImpl;
import ch.entwine.weblounge.common.impl.request.WebloungeResponseImpl;
import ch.entwine.weblounge.common.request.WebloungeRequest;
import ch.entwine.weblounge.common.request.WebloungeResponse;
import ch.entwine.weblounge.common.site.Environment;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.TryCatchFinally;

/**
* Base class for weblounge tags which implements most of the standard
* <code>HTML 4</code> tag attributes.
*/
public class WebloungeTag extends BodyTagSupport implements TryCatchFinally {

  /** Serial version id */
  private static final long serialVersionUID = 1754816467985401658L;

  /** The logging facility */
  private static final Logger logger = LoggerFactory.getLogger(WebloungeTag.class);

  /** Css class attribute */
  protected String css = null;

  /** Css style attribute */
  protected String style = null;

  /** lang attribute */
  protected String lang = null;

  /** dir (reading direction) attribute */
  protected String dir = null;

  /** Html title */
  protected String title = null;

  /** Html name */
  protected String name = null;

  /** OnClick Event */
  protected String onclick = null;

  /** OnDblClick Event */
  protected String ondblclick = null;

  /** OnMouseDown Event */
  protected String onmousedown = null;

  /** OnMouseUp Event */
  protected String onmouseup = null;

  /** OnMouseMove Event */
  protected String onmousemove = null;

  /** OnMouseOver Event */
  protected String onmouseover = null;

  /** OnMouseOut Event */
  protected String onmouseout = null;

  /** OnKeyDown Event */
  protected String onkeydown = null;

  /** OnKeyPress Event */
  protected String onkeypress = null;

  /** OnKeyUp Event */
  protected String onkeyup = null;

  /** The weblounge request */
  protected WebloungeRequest request = null;

  /** The weblounge response */
  protected WebloungeResponse response = null;

  /** The stash */
  protected Map<String, Object> stash = new HashMap<String, Object>();

  /** The attributes that were added by this tag instance */
  protected List<String> attributes = new ArrayList<String>();

  /**
   * Resets the properties of this tag to default values. This method is called
   * between <strong>every</strong> request.
   * <p>
   * If you override this method make sure you call <code>super.reset()</code>
   */
  protected void reset() {
    css = null;
    style = null;
    lang = null;
    dir = null;
    title = null;
    name = null;
    onclick = null;
    ondblclick = null;
    onmousedown = null;
    onmouseup = null;
    onmousemove = null;
    onmouseover = null;
    onmouseout = null;
    onkeydown = null;
    onkeypress = null;
    onkeyup = null;
    request = null;
    response = null;
    stash.clear();
    attributes.clear();
  }

  /**
   * Sets the standard <code>HTML</code> <code>class</code> attribute.
   *
   * @param c
   *          the css class
   */
  public void setClass(String c) {
    css = c;
  }

  /**
   * Sets the standard <code>HTML</code> <code>class</code> attribute.
   *
   * @param c
   *          the css class
   */
  public void setCss(String c) {
    css = c;
  }

  /**
   * Adds the class to the css class attribute.
   *
   * @param c
   *          the class name
   */
  protected void addCssClass(String c) {
    if (StringUtils.trimToNull(c) == null)
      return;
    if (css == null)
      css = c;
    else if (!css.startsWith(c + " ") && !css.endsWith(" " + c) && !css.contains(" " + c + " "))
      css += " " + c;
  }

  /**
   * Sets the standard <code>HTML</code> <code>style</code> attribute.
   *
   * @param style
   *          the html style
   */
  public void setStyle(String style) {
    this.style = style;
  }

  /**
   * Sets the standard <code>HTML</code> <code>lang</code> attribute.
   *
   * @param lang
   *          the language
   */
  public void setLang(String lang) {
    this.lang = lang;
  }

  /**
   * Sets the standard <code>HTML</code> <code>dir</code> attribute.
   *
   * @param dir
   *          the reading direction
   */
  public void setDir(String dir) {
    this.dir = dir;
  }

  /**
   * Sets the standard <code>HTML</code> <code>title</code> attribute which is
   * used to display tooltips.
   *
   * @param title
   *          the html title
   */
  public void setTitle(String title) {
    this.title = title;
  }

  /**
   * Sets the standard <code>HTML</code> <code>name</code> attribute.
   *
   * @param name
   *          the html name
   */
  public void setName(String name) {
    this.name = name;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onclick</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnclick(String handler) {
    this.onclick = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onclick</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnClick(String handler) {
    this.onclick = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>ondblclick</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOndblclick(String handler) {
    this.ondblclick = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>ondblclick</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnDblClick(String handler) {
    this.ondblclick = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmousedown</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnmousedown(String handler) {
    this.onmousedown = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmousedown</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnMouseDown(String handler) {
    this.onmousedown = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmousemove</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnmousemove(String handler) {
    this.onmousemove = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmousemove</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnMouseMove(String handler) {
    this.onmousemove = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseout</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnmouseout(String handler) {
    this.onmouseout = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseout</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnMouseOut(String handler) {
    this.onmouseout = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseover</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnmouseover(String handler) {
    this.onmouseover = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseover</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnMouseOver(String handler) {
    this.onmouseover = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseup</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnmouseup(String handler) {
    this.onmouseup = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onmouseup</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnMouseUp(String handler) {
    this.onmouseup = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeydown</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnkeydown(String handler) {
    this.onkeydown = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeydown</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnKeyDown(String handler) {
    this.onkeydown = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeypress</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnkeypress(String handler) {
    this.onkeypress = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeypress</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnKeyPress(String handler) {
    this.onkeypress = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeyup</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnkeyup(String handler) {
    this.onkeyup = handler;
  }

  /**
   * Sets the standard <code>HTML</code> event <code>onkeyup</code> event
   * handler.
   *
   * @param handler
   *          the event handler code
   */
  public void setOnKeyUp(String handler) {
    this.onkeyup = handler;
  }

  /**
   * Returns the weblounge request. This method searches the probably wrapped
   * request hierarchy for the original weblounge request.
   *
   * @return the weblounge request
   */
  public WebloungeRequest getRequest() {
    return unwrapRequest(pageContext.getRequest());
  }

  /**
   * Returns the weblounge response. This method searches the probably wrapped
   * response hierarchy for the original weblounge response.
   *
   * @return the weblounge response
   */
  public WebloungeResponse getResponse() {
    return unwrapResponse(pageContext.getResponse());
  }

  /**
   * Returns the standard attributes ready to inserted in an HTML tag.
   *
   * @return the standard HTML attributes
   */
  protected Map<String, String> getStandardAttributes() {
    Map<String, String> attributes = new HashMap<String, String>();
    if (css != null)
      attributes.put("class", css);
    if (getId() != null)
      attributes.put("id", getId());
    if (name != null)
      attributes.put("name", name);
    if (style != null)
      attributes.put("style", style);
    if (lang != null)
      attributes.put("lang", lang);
    if (dir != null)
      attributes.put("dir", dir);
    if (title != null)
      attributes.put("title", title);

    // Mouse events
    if (onclick != null)
      attributes.put("onclick", name);
    if (ondblclick != null)
      attributes.put("ondblclick", ondblclick);
    if (onmousedown != null)
      attributes.put("onmousedown", onmousedown);
    if (onmousemove != null)
      attributes.put("onmousemove", onmousemove);
    if (onmouseout != null)
      attributes.put("onmouseout", onmouseout);
    if (onmouseover != null)
      attributes.put("onmouseover", onmouseover);
    if (onmouseup != null)
      attributes.put("onmouseup", onmouseup);

    // Keyboard events
    if (onkeydown != null)
      attributes.put("onkeydown", onkeydown);
    if (onkeypress != null)
      attributes.put("onkeypress", onkeypress);
    if (onkeyup != null)
      attributes.put("onkeyup", onkeyup);

    return attributes;
  }

  /**
   * Overwritten to extract <code>WebloungeRequest</code> and
   * <code>WebloungeResponse</code>.
   *
   * @see javax.servlet.jsp.tagext.Tag#setPageContext(javax.servlet.jsp.PageContext)
   */
  @Override
  public void setPageContext(PageContext ctxt) {
    super.setPageContext(ctxt);
    request = unwrapRequest(pageContext.getRequest());
    response = unwrapResponse(pageContext.getResponse());
  }

  /**
   * Stores any original value for the given attribute away for later reference.
   *
   * @param attribute
   *          the attribute name
   */
  protected void stashAttribute(String attribute) {
    stashAndSetAttribute(attribute, null);
  }

  /**
   * Sets the attribute in the page context and stores any original value away
   * for later reference.
   *
   * @param attribute
   *          the attribute name
   * @param value
   *          the value
   */
  protected void stashAndSetAttribute(String attribute, Object value) {
    Object existingValue = pageContext.getAttribute(attribute);

    // If there is a value already, keep it for later reference
    if (existingValue != null) {
      String existingType = existingValue.getClass().getName();
      logger.debug("Stashing context item '{}' of type {}", attribute, existingType);
      stash.put(attribute, existingValue);
    }

    // Set the attribute
    if (value != null) {
      pageContext.setAttribute(attribute, value);
    }
    attributes.add(attribute);
  }

  /**
   * Removes the given attribute from the page context and replaces it with a
   * potentially stashed value.
   *
   * @param attribute
   *          the attribute name
   */
  protected void removeAndUnsstashAttribute(String attribute) {
    Object value = stash.remove(attribute);
    if (value != null) {
      String existingType = value.getClass().getName();
      logger.debug("Applying stashed page context item '{}' of type {}", attribute, existingType);
      pageContext.setAttribute(attribute, value);
    } else {
      pageContext.removeAttribute(attribute);
    }
    attributes.remove(attribute);
  }

  /**
   * Removes all attributes that have been set by the current tag instance from
   * the page context and replaces them with potentially stashed values.
   */
  protected void removeAndUnstashAttributes() {
    for (String attribute : attributes) {
      Object value = stash.remove(attribute);
      if (value != null) {
        String existingType = value.getClass().getName();
        logger.debug("Applying stashed page context item '{}' of type {}", attribute, existingType);
        pageContext.setAttribute(attribute, value);
      } else {
        pageContext.removeAttribute(attribute);
      }
    }
    attributes.clear();

    // Make sure we are not missing out on any stash values
    for (Map.Entry<String, Object> stashEntry : stash.entrySet()) {
      String attribute = stashEntry.getKey();
      Object value = stashEntry.getValue();
      String existingType = value.getClass().getName();
      logger.debug("Applying stashed page context item '{}' of type {}", attribute, existingType);
      pageContext.setAttribute(attribute, value);
    }
    stash.clear();
  }

  /**
   * Returns the map of attributes as a string. If there are no attributes in
   * the map, an empty string is returned.
   *
   * @param attributes
   *          the attributes as a string
   * @return the attributes ready to be added to a tag
   */
  protected static String attributesToString(Map<String, String> attributes) {
    if (attributes == null || attributes.size() == 0)
      return "";
    StringBuffer buf = new StringBuffer();
    for (Map.Entry<String, String> attribute : attributes.entrySet()) {
      if (buf.length() > 0)
        buf.append(" ");
      buf.append(attribute.getKey());
      buf.append("=\"");
      buf.append(attribute.getValue());
      buf.append("\"");
    }
    return buf.toString();
  }

  /**
   * Extract the wrapped <code>WebloungeResponse</code> from a <code>
   * ServletResponse</code>.
   *
   * @param response
   *          the wrapping response
   * @return the wrapped <code>WebloungeResponse</code> or <code>null</code> if
   *         no such response exists
   */
  private static WebloungeResponse unwrapResponse(ServletResponse response) {
    while (response != null) {
      if (response instanceof WebloungeResponse)
        return (WebloungeResponse) response;
      if (!(response instanceof ServletResponseWrapper))
        break;
      response = ((ServletResponseWrapper) response).getResponse();
    }

    // Last resort
    if (response instanceof HttpServletResponse)
      return new WebloungeResponseImpl((HttpServletResponse) response);

    return null;
  }

  /**
   * Extract the wrapped <code>WebloungeRequest</code> from a <code>
   * ServletRequest</code> .
   *
   * @param request
   *          the wrapping request
   * @return the wrapped <code>WebloungeRequest</code> or <code>null</code> if
   *         no such response exists
   */
  private static WebloungeRequest unwrapRequest(ServletRequest request) {
    while (request != null) {
      if (request instanceof WebloungeRequest)
        return (WebloungeRequest) request;
      if (!(request instanceof ServletRequestWrapper))
        break;
      request = ((ServletRequestWrapper) request).getRequest();
    }

    // Last resort
    if (request instanceof HttpServletRequest) {
      logger.warn("Found vanilla servlet request, defaulting to production environment");
      // TOOD: Properly determine the environment
      return new WebloungeRequestImpl((HttpServletRequest) request, Environment.Production);
    }

    return null;
  }

  /**
   * {@inheritDoc}
   *
   * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
   */
  @Override
  public int doStartTag() throws JspException {

    // Don't do work if not needed (which is the case during precompilation)
    if (RequestUtils.isPrecompileRequest(request))
      return SKIP_BODY;

    return super.doStartTag();
  }

  /**
   * {@inheritDoc}
   *
   * @see javax.servlet.jsp.tagext.TryCatchFinally#doCatch(java.lang.Throwable)
   */
  public void doCatch(Throwable t) throws Throwable {
    // Don't log errors during tag execution while precompiling
    if (RequestUtils.isPrecompileRequest(request)) {
      return;
    }

    logger.warn("Error executing jsp tag {} on {}", getClass().getName(), request.getUrl());
    logger.warn(t.getMessage(), t);
  }

  /**
   * {@inheritDoc}
   *
   * @see javax.servlet.jsp.tagext.TryCatchFinally#doFinally()
   */
  public void doFinally() {
    // Make sure the state of the tag is reset between every use
    reset();
  }

}
TOP

Related Classes of ch.entwine.weblounge.taglib.WebloungeTag

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.