/**
  * Get the state.
  *
  * <p>In JSF 2.2 it is required by the specification that the view state hidden input in each
  * h:form has a unique id. So we have to call this method multiple times as each h:form needs to
  * generate the element id for itself.
  *
  * @param stateManager the state manager.
  * @param origWriter the original response writer.
  * @return the state.
  * @throws IOException when an I/O error occurs.
  */
 private StringBuilder getState(StateManager stateManager, ResponseWriter origWriter)
     throws IOException {
   FastStringWriter stateWriter =
       new FastStringWriter((stateManager.isSavingStateInClient(context)) ? bufSize : 128);
   context.setResponseWriter(origWriter.cloneWithWriter(stateWriter));
   if (state == null) {
     state = stateManager.saveView(context);
   }
   stateManager.writeState(context, state);
   context.setResponseWriter(origWriter);
   StringBuilder stateBuilder = stateWriter.getBuffer();
   return stateBuilder;
 }
Beispiel #2
0
  /**
   * Write a properly escaped attribute name and the corresponding value. The value text will be
   * converted to a String if necessary. This method may only be called after a call to <code>
   * startElement()</code>, and before the opened element has been closed.
   *
   * @param name Attribute name to be added
   * @param value Attribute value to be added
   * @param componentPropertyName The name of the component property to which this attribute
   *     argument applies. This argument may be <code>null</code>.
   * @throws IllegalStateException if this method is called when there is no currently open element
   * @throws IOException if an input/output error occurs
   * @throws NullPointerException if <code>name</code> is <code>null</code>
   */
  public void writeAttribute(String name, Object value, String componentPropertyName)
      throws IOException {

    if (name == null) {
      throw new NullPointerException(
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "name"));
    }
    if (value == null) {
      return;
    }

    if (isCdata) {
      return;
    }

    if (name.equalsIgnoreCase("src") && isScriptOrStyle()) {
      scriptOrStyleSrc = true;
    }

    Class valueClass = value.getClass();

    // Output Boolean values specially
    if (valueClass == Boolean.class) {
      if (Boolean.TRUE.equals(value)) {
        // NOTE:  HTML 4.01 states that boolean attributes
        //        may legally take a single value which is the
        //        name of the attribute itself or appear using
        //        minimization.
        //  http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.3.4.2
        attributesBuffer.write(' ');
        attributesBuffer.write(name);
        attributesBuffer.write("=\"");
        attributesBuffer.write(name);
        attributesBuffer.write('"');
      }
    } else {
      attributesBuffer.write(' ');
      attributesBuffer.write(name);
      attributesBuffer.write("=\"");
      // write the attribute value
      String val = value.toString();
      ensureTextBufferCapacity(val);
      HtmlUtils.writeAttribute(
          attributesBuffer,
          escapeUnicode,
          escapeIso,
          buffer,
          val,
          textBuffer,
          isScriptInAttributeValueEnabled);
      attributesBuffer.write('"');
    }
  }
Beispiel #3
0
  /**
   * This method automatically closes a previous element (if not already closed).
   *
   * @throws IOException if an error occurs writing
   */
  private void closeStartIfNecessary() throws IOException {

    if (closeStart) {
      flushAttributes();
      writer.write('>');
      closeStart = false;
      if (isScriptOrStyle() && !scriptOrStyleSrc) {
        isXhtml = getContentType().equals(RIConstants.XHTML_CONTENT_TYPE);
        if (isXhtml) {
          if (!writingCdata) {
            if (isScript) {
              writer.write("\n//<![CDATA[\n");
            } else {
              writer.write("\n<![CDATA[\n");
            }
          }
        } else {
          if (isScriptHidingEnabled) {
            writer.write("\n<!--\n");
          }
        }
        origWriter = writer;
        if (scriptBuffer == null) {
          scriptBuffer = new FastStringWriter(1024);
        }
        scriptBuffer.reset();
        writer = scriptBuffer;
        isScript = false;
        isStyle = false;
      }
    }
  }
Beispiel #4
0
  /**
   * Write a properly encoded URI attribute name and the corresponding value. The value text will be
   * converted to a String if necessary). This method may only be called after a call to <code>
   * startElement()</code>, and before the opened element has been closed.
   *
   * @param name Attribute name to be added
   * @param value Attribute value to be added
   * @param componentPropertyName The name of the component property to which this attribute
   *     argument applies. This argument may be <code>null</code>.
   * @throws IllegalStateException if this method is called when there is no currently open element
   * @throws IOException if an input/output error occurs
   * @throws NullPointerException if <code>name</code> or <code>value</code> is <code>null</code>
   */
  public void writeURIAttribute(String name, Object value, String componentPropertyName)
      throws IOException {

    if (name == null) {
      throw new NullPointerException(
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "name"));
    }
    if (value == null) {
      throw new NullPointerException(
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "value"));
    }

    if (isCdata) {
      return;
    }

    if (name.equalsIgnoreCase("src") && isScriptOrStyle()) {
      scriptOrStyleSrc = true;
    }

    attributesBuffer.write(' ');
    attributesBuffer.write(name);
    attributesBuffer.write("=\"");

    String stringValue = value.toString();
    ensureTextBufferCapacity(stringValue);
    // Javascript URLs should not be URL-encoded
    if (stringValue.startsWith("javascript:")) {
      HtmlUtils.writeAttribute(
          attributesBuffer,
          escapeUnicode,
          escapeIso,
          buffer,
          stringValue,
          textBuffer,
          isScriptInAttributeValueEnabled);
    } else {
      HtmlUtils.writeURL(attributesBuffer, stringValue, textBuffer, encoding);
    }

    attributesBuffer.write('"');
  }
Beispiel #5
0
  private void flushAttributes() throws IOException {

    // a little complex, but the end result is, potentially, two
    // fewer temp objects created per call.
    StringBuilder b = attributesBuffer.getBuffer();
    int totalLength = b.length();
    if (totalLength != 0) {
      int curIdx = 0;
      while (curIdx < totalLength) {
        if ((totalLength - curIdx) > buffer.length) {
          int end = curIdx + buffer.length;
          b.getChars(curIdx, end, buffer, 0);
          writer.write(buffer);
          curIdx += buffer.length;
        } else {
          int len = totalLength - curIdx;
          b.getChars(curIdx, curIdx + len, buffer, 0);
          writer.write(buffer, 0, len);
          curIdx += len;
        }
      }
      attributesBuffer.reset();
    }
  }
  /**
   * Write directly from our FastStringWriter to the provided writer.
   *
   * @throws IOException if an error occurs
   */
  public void flushToWriter() throws IOException {

    // Save the state to a new instance of StringWriter to
    // avoid multiple serialization steps if the view contains
    // multiple forms.
    StateManager stateManager = Util.getStateManager(context);
    ResponseWriter origWriter = context.getResponseWriter();
    StringBuilder stateBuilder = getState(stateManager, origWriter);
    StringBuilder builder = fWriter.getBuffer();
    // begin writing...
    int totalLen = builder.length();
    int stateLen = stateBuilder.length();
    int pos = 0;
    int tildeIdx = getNextDelimiterIndex(builder, pos);
    while (pos < totalLen) {
      if (tildeIdx != -1) {
        if (tildeIdx > pos && (tildeIdx - pos) > bufSize) {
          // there's enough content before the first ~
          // to fill the entire buffer
          builder.getChars(pos, (pos + bufSize), buf, 0);
          orig.write(buf);
          pos += bufSize;
        } else {
          // write all content up to the first '~'
          builder.getChars(pos, tildeIdx, buf, 0);
          int len = (tildeIdx - pos);
          orig.write(buf, 0, len);
          // now check to see if the state saving string is
          // at the begining of pos, if so, write our
          // state out.
          if (builder.indexOf(RIConstants.SAVESTATE_FIELD_MARKER, pos) == tildeIdx) {
            // buf is effectively zero'd out at this point
            int statePos = 0;
            while (statePos < stateLen) {
              if ((stateLen - statePos) > bufSize) {
                // enough state to fill the buffer
                stateBuilder.getChars(statePos, (statePos + bufSize), buf, 0);
                orig.write(buf);
                statePos += bufSize;
              } else {
                int slen = (stateLen - statePos);
                stateBuilder.getChars(statePos, stateLen, buf, 0);
                orig.write(buf, 0, slen);
                statePos += slen;
              }
            }
            // push us past the last '~' at the end of the marker
            pos += (len + STATE_MARKER_LEN);
            tildeIdx = getNextDelimiterIndex(builder, pos);

            stateBuilder = getState(stateManager, origWriter);
            stateLen = stateBuilder.length();
          } else {
            pos = tildeIdx;
            tildeIdx = getNextDelimiterIndex(builder, tildeIdx + 1);
          }
        }
      } else {
        // we've written all of the state field markers.
        // finish writing content
        if (totalLen - pos > bufSize) {
          // there's enough content to fill the buffer
          builder.getChars(pos, (pos + bufSize), buf, 0);
          orig.write(buf);
          pos += bufSize;
        } else {
          // we're near the end of the response
          builder.getChars(pos, totalLen, buf, 0);
          int len = (totalLen - pos);
          orig.write(buf, 0, len);
          pos += (len + 1);
        }
      }
    }

    // all state has been written.  Have 'out' point to the
    // response so that all subsequent writes will make it to the
    // browser.
    out = orig;
  }