Program: 35839
Project: 35839
Buggy source:
/** 
 * Retrieves a resource from the provider application and parses it to find tags to be replaced by contents from other providers. Sample syntax used for includes : <ul> <li>&lt;!--$includeblock$provider$page$blockname$--&gt;</li> <li>&lt;!--$beginincludetemplate$provider$page$templatename$--&gt;</li> <li>&lt;!--$beginput$name$--&gt;</li> </ul> Sample syntax used inside included contents for template and block definition : <ul> <li>&lt;!--$beginblock$name$--&gt;</li> <li>&lt;!--$begintemplate$name$--&gt;</li> <li>&lt;!--$beginparam$name$--&gt;</li> </ul> Aggregation is always in "proxy mode" that means cookies or parameters from the original request are transmitted to the target server. NB: Cookies and parameters are not transmitted to templates or blocks invoked by the page.
 * @param relUrl the relative URL to the resource
 * @param request the request
 * @param response the response
 * @throws IOException
 * @throws AggregationSyntaxException
 */
public final void aggregate(String relUrl,HttpServletRequest request,HttpServletResponse response) throws IOException, AggregationSyntaxException {
  Target target=new Target(relUrl,getContext(request),null,request);
  target.setProxyMode(true);
  StringOutput stringOutput=getResourceAsString(target);
  if (stringOutput.getStatusCode() == HttpServletResponse.SC_MOVED_PERMANENTLY || stringOutput.getStatusCode() == HttpServletResponse.SC_MOVED_TEMPORARILY) {
    response.setStatus(stringOutput.getStatusCode());
    response.setHeader("String_Node_Str",stringOutput.getLocation());
    return;
  }
  stringOutput.copyHeaders(response);
  String content=stringOutput.toString();
  if (content == null)   return;
  response.setCharacterEncoding(stringOutput.getCharset());
  Writer writer=response.getWriter();
  int currentPosition=0;
  int previousPosition;
  int endPosition;
  String currentTag;
  StringTokenizer stringTokenizer;
  String tagName;
  String provider;
  String page;
  String blockOrTemplate;
  while (currentPosition > -1) {
    previousPosition=currentPosition;
    currentPosition=content.indexOf("String_Node_Str",currentPosition);
    if (currentPosition > -1) {
      writer.append(content,previousPosition,currentPosition);
      endPosition=content.indexOf("String_Node_Str",currentPosition);
      if (endPosition == -1)       throw new AggregationSyntaxException("String_Node_Str");
      currentTag=content.substring(currentPosition + 4,endPosition);
      log.debug("String_Node_Str" + currentTag);
      currentPosition=endPosition + 3;
      stringTokenizer=new StringTokenizer(currentTag,"String_Node_Str");
      if (stringTokenizer.countTokens() < 3)       throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      tagName=stringTokenizer.nextToken();
      provider=stringTokenizer.nextToken();
      page=stringTokenizer.nextToken();
      if (stringTokenizer.hasMoreTokens())       blockOrTemplate=stringTokenizer.nextToken();
 else       blockOrTemplate=null;
      if (stringTokenizer.hasMoreTokens())       throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      if ("String_Node_Str".equals(tagName)) {
        Driver.getInstance(provider).renderBlock(page,blockOrTemplate,writer,getContext(request),null,null);
      }
 else       if ("String_Node_Str".equals(tagName)) {
        endPosition=content.indexOf("String_Node_Str");
        if (endPosition < 0)         throw new AggregationSyntaxException("String_Node_Str" + currentTag);
        Driver.getInstance(provider).aggregateTemplate(page,blockOrTemplate,content.substring(currentPosition,endPosition),writer,request);
        currentPosition=endPosition + 27;
      }
 else {
        throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      }
    }
 else {
      writer.append(content,previousPosition,content.length());
    }
  }
}

Fixed version (ground truth):
/** 
 * Retrieves a resource from the provider application and parses it to find tags to be replaced by contents from other providers. Sample syntax used for includes : <ul> <li>&lt;!--$includeblock$provider$page$blockname$--&gt;</li> <li>&lt;!--$beginincludetemplate$provider$page$templatename$--&gt;</li> <li>&lt;!--$beginput$name$--&gt;</li> </ul> Sample syntax used inside included contents for template and block definition : <ul> <li>&lt;!--$beginblock$name$--&gt;</li> <li>&lt;!--$begintemplate$name$--&gt;</li> <li>&lt;!--$beginparam$name$--&gt;</li> </ul> Aggregation is always in "proxy mode" that means cookies or parameters from the original request are transmitted to the target server. NB: Cookies and parameters are not transmitted to templates or blocks invoked by the page.
 * @param relUrl the relative URL to the resource
 * @param request the request
 * @param response the response
 * @throws IOException If an IOException occurs while writing to theresponse
 * @throws AggregationSyntaxException If the page contains incorrect tags
 */
public final void aggregate(String relUrl,HttpServletRequest request,HttpServletResponse response) throws IOException, AggregationSyntaxException {
  Target target=new Target(relUrl,getContext(request),null,request);
  request.setCharacterEncoding(config.getUriEncoding());
  target.setProxyMode(true);
  StringOutput stringOutput=getResourceAsString(target);
  if (stringOutput.getStatusCode() == HttpServletResponse.SC_MOVED_PERMANENTLY || stringOutput.getStatusCode() == HttpServletResponse.SC_MOVED_TEMPORARILY) {
    response.setStatus(stringOutput.getStatusCode());
    response.setHeader("String_Node_Str",stringOutput.getLocation());
    return;
  }
  stringOutput.copyHeaders(response);
  String content=stringOutput.toString();
  if (content == null)   return;
  response.setCharacterEncoding(stringOutput.getCharset());
  Writer writer=response.getWriter();
  int currentPosition=0;
  int previousPosition;
  int endPosition;
  String currentTag;
  StringTokenizer stringTokenizer;
  String tagName;
  String provider;
  String page;
  String blockOrTemplate;
  while (currentPosition > -1) {
    previousPosition=currentPosition;
    currentPosition=content.indexOf("String_Node_Str",currentPosition);
    if (currentPosition > -1) {
      writer.append(content,previousPosition,currentPosition);
      endPosition=content.indexOf("String_Node_Str",currentPosition);
      if (endPosition == -1)       throw new AggregationSyntaxException("String_Node_Str");
      currentTag=content.substring(currentPosition + 4,endPosition);
      log.debug("String_Node_Str" + currentTag);
      currentPosition=endPosition + 3;
      stringTokenizer=new StringTokenizer(currentTag,"String_Node_Str");
      if (stringTokenizer.countTokens() < 3)       throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      tagName=stringTokenizer.nextToken();
      provider=stringTokenizer.nextToken();
      page=stringTokenizer.nextToken();
      if (stringTokenizer.hasMoreTokens())       blockOrTemplate=stringTokenizer.nextToken();
 else       blockOrTemplate=null;
      if (stringTokenizer.hasMoreTokens())       throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      if ("String_Node_Str".equals(tagName)) {
        Driver.getInstance(provider).renderBlock(page,blockOrTemplate,writer,getContext(request),null,null);
      }
 else       if ("String_Node_Str".equals(tagName)) {
        endPosition=content.indexOf("String_Node_Str");
        if (endPosition < 0)         throw new AggregationSyntaxException("String_Node_Str" + currentTag);
        Driver.getInstance(provider).aggregateTemplate(page,blockOrTemplate,content.substring(currentPosition,endPosition),writer,request);
        currentPosition=endPosition + 27;
      }
 else {
        throw new AggregationSyntaxException("String_Node_Str" + currentTag);
      }
    }
 else {
      writer.append(content,previousPosition,content.length());
    }
  }
}