/**
  * 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;
 }
Example #2
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;
  }