All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwtexpui.safehtml.client.SafeHtmlBuilder Maven / Gradle / Ivy

// Copyright (C) 2009 The Android Open Source 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 com.google.gwtexpui.safehtml.client;

import com.google.gwt.core.client.GWT;

/** Safely constructs a {@link SafeHtml}, escaping user provided content. */
public class SafeHtmlBuilder extends SafeHtml {
  private static final long serialVersionUID = 1L;

  private static final Impl impl;

  static {
    if (GWT.isClient()) {
      impl = new ClientImpl();
    } else {
      impl = new ServerImpl();
    }
  }

  private final BufferDirect dBuf;
  private Buffer cb;

  private BufferSealElement sBuf;
  private AttMap att;

  public SafeHtmlBuilder() {
    cb = dBuf = new BufferDirect();
  }

  /** @return true if this builder has not had an append occur yet. */
  public boolean isEmpty() {
    return dBuf.isEmpty();
  }

  /** @return true if this builder has content appended into it. */
  public boolean hasContent() {
    return !isEmpty();
  }

  public SafeHtmlBuilder append(boolean in) {
    cb.append(in);
    return this;
  }

  public SafeHtmlBuilder append(char in) {
    switch (in) {
      case '&':
        cb.append("&");
        break;

      case '>':
        cb.append(">");
        break;

      case '<':
        cb.append("<");
        break;

      case '"':
        cb.append(""");
        break;

      case '\'':
        cb.append("'");
        break;

      default:
        cb.append(in);
        break;
    }
    return this;
  }

  public SafeHtmlBuilder append(int in) {
    cb.append(in);
    return this;
  }

  public SafeHtmlBuilder append(long in) {
    cb.append(in);
    return this;
  }

  public SafeHtmlBuilder append(float in) {
    cb.append(in);
    return this;
  }

  public SafeHtmlBuilder append(double in) {
    cb.append(in);
    return this;
  }

  /** Append already safe HTML as-is, avoiding double escaping. */
  public SafeHtmlBuilder append(com.google.gwt.safehtml.shared.SafeHtml in) {
    if (in != null) {
      cb.append(in.asString());
    }
    return this;
  }

  /** Append already safe HTML as-is, avoiding double escaping. */
  public SafeHtmlBuilder append(SafeHtml in) {
    if (in != null) {
      cb.append(in.asString());
    }
    return this;
  }

  /** Append the string, escaping unsafe characters. */
  public SafeHtmlBuilder append(String in) {
    if (in != null) {
      impl.escapeStr(this, in);
    }
    return this;
  }

  /** Append the string, escaping unsafe characters. */
  public SafeHtmlBuilder append(StringBuilder in) {
    if (in != null) {
      append(in.toString());
    }
    return this;
  }

  /** Append the string, escaping unsafe characters. */
  public SafeHtmlBuilder append(StringBuffer in) {
    if (in != null) {
      append(in.toString());
    }
    return this;
  }

  /** Append the result of toString(), escaping unsafe characters. */
  public SafeHtmlBuilder append(Object in) {
    if (in != null) {
      append(in.toString());
    }
    return this;
  }

  /** Append the string, escaping unsafe characters. */
  public SafeHtmlBuilder append(CharSequence in) {
    if (in != null) {
      escapeCS(this, in);
    }
    return this;
  }

  /**
   * Open an element, appending "{@code }" to the buffer.
   *
   * 

After the element is open the attributes may be manipulated until the next {@code append}, * {@code openElement}, {@code closeSelf} or {@code closeElement} call. * * @param tagName name of the HTML element to open. */ public SafeHtmlBuilder openElement(String tagName) { assert isElementName(tagName); cb.append("<"); cb.append(tagName); if (sBuf == null) { att = new AttMap(); sBuf = new BufferSealElement(this); } att.reset(tagName); cb = sBuf; return this; } /** * Get an attribute of the last opened element. * * @param name name of the attribute to read. * @return the attribute value, as a string. The empty string if the attribute has not been * assigned a value. The returned string is the raw (unescaped) value. */ public String getAttribute(String name) { assert isAttributeName(name); assert cb == sBuf; return att.get(name); } /** * Set an attribute of the last opened element. * * @param name name of the attribute to set. * @param value value to assign; any existing value is replaced. The value is escaped (if * necessary) during the assignment. */ public SafeHtmlBuilder setAttribute(String name, String value) { assert isAttributeName(name); assert cb == sBuf; att.set(name, value != null ? value : ""); return this; } /** * Set an attribute of the last opened element. * * @param name name of the attribute to set. * @param value value to assign, any existing value is replaced. */ public SafeHtmlBuilder setAttribute(String name, int value) { return setAttribute(name, String.valueOf(value)); } /** * Append a new value into a whitespace delimited attribute. * *

If the attribute is not yet assigned, this method sets the attribute. If the attribute is * already assigned, the new value is appended onto the end, after appending a single space to * delimit the values. * * @param name name of the attribute to append onto. * @param value additional value to append. */ public SafeHtmlBuilder appendAttribute(String name, String value) { if (value != null && value.length() > 0) { final String e = getAttribute(name); return setAttribute(name, e.length() > 0 ? e + " " + value : value); } return this; } /** Set the height attribute of the current element. */ public SafeHtmlBuilder setHeight(int height) { return setAttribute("height", height); } /** Set the width attribute of the current element. */ public SafeHtmlBuilder setWidth(int width) { return setAttribute("width", width); } /** Set the CSS class name for this element. */ public SafeHtmlBuilder setStyleName(String style) { assert isCssName(style); return setAttribute("class", style); } /** * Add an additional CSS class name to this element. * *

If no CSS class name has been specified yet, this method initializes it to the single name. */ public SafeHtmlBuilder addStyleName(String style) { assert isCssName(style); return appendAttribute("class", style); } private void sealElement0() { assert cb == sBuf; cb = dBuf; att.onto(cb, this); } Buffer sealElement() { sealElement0(); cb.append(">"); return cb; } /** Close the current element with a self closing suffix ("/ >"). */ public SafeHtmlBuilder closeSelf() { sealElement0(); cb.append(" />"); return this; } /** Append a closing tag for the named element. */ public SafeHtmlBuilder closeElement(String name) { assert isElementName(name); cb.append(""); return this; } /** Append "&nbsp;" - a non-breaking space, useful in empty table cells. */ public SafeHtmlBuilder nbsp() { cb.append(" "); return this; } /** Append "<br />" - a line break with no attributes */ public SafeHtmlBuilder br() { cb.append("
"); return this; } /** Append "<tr>"; attributes may be set if needed */ public SafeHtmlBuilder openTr() { return openElement("tr"); } /** Append "</tr>" */ public SafeHtmlBuilder closeTr() { return closeElement("tr"); } /** Append "<td>"; attributes may be set if needed */ public SafeHtmlBuilder openTd() { return openElement("td"); } /** Append "</td>" */ public SafeHtmlBuilder closeTd() { return closeElement("td"); } /** Append "<th>"; attributes may be set if needed */ public SafeHtmlBuilder openTh() { return openElement("th"); } /** Append "</th>" */ public SafeHtmlBuilder closeTh() { return closeElement("th"); } /** Append "<div>"; attributes may be set if needed */ public SafeHtmlBuilder openDiv() { return openElement("div"); } /** Append "</div>" */ public SafeHtmlBuilder closeDiv() { return closeElement("div"); } /** Append "<span>"; attributes may be set if needed */ public SafeHtmlBuilder openSpan() { return openElement("span"); } /** Append "</span>" */ public SafeHtmlBuilder closeSpan() { return closeElement("span"); } /** Append "<a>"; attributes may be set if needed */ public SafeHtmlBuilder openAnchor() { return openElement("a"); } /** Append "</a>" */ public SafeHtmlBuilder closeAnchor() { return closeElement("a"); } /** Append "<param name=... value=... />". */ public SafeHtmlBuilder paramElement(String name, String value) { openElement("param"); setAttribute("name", name); setAttribute("value", value); return closeSelf(); } /** @return an immutable {@link SafeHtml} representation of the buffer. */ public SafeHtml toSafeHtml() { return new SafeHtmlString(asString()); } @Override public String asString() { return cb.toString(); } private static void escapeCS(SafeHtmlBuilder b, CharSequence in) { for (int i = 0; i < in.length(); i++) { b.append(in.charAt(i)); } } private static boolean isElementName(String name) { return name.matches("^[a-zA-Z][a-zA-Z0-9_-]*$"); } private static boolean isAttributeName(String name) { return isElementName(name); } private static boolean isCssName(String name) { return isElementName(name); } private abstract static class Impl { abstract void escapeStr(SafeHtmlBuilder b, String in); } private static class ServerImpl extends Impl { @Override void escapeStr(SafeHtmlBuilder b, String in) { SafeHtmlBuilder.escapeCS(b, in); } } private static class ClientImpl extends Impl { @Override void escapeStr(SafeHtmlBuilder b, String in) { b.cb.append(escape(in)); } private static native String escape(String src) /*-{ return src.replace(/&/g,'&') .replace(/>/g,'>') .replace(/





© 2015 - 2024 Weber Informatics LLC | Privacy Policy