• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
WOHyperlink, BOZO_AMPERSAND Revisited
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

WOHyperlink, BOZO_AMPERSAND Revisited


  • Subject: WOHyperlink, BOZO_AMPERSAND Revisited
  • From: Alex Johnson <email@hidden>
  • Date: Mon, 30 Jul 2007 09:47:29 -0700

Hi,

Back in Feb 2006, there was a discussion about a bug in WebObjects 5.3.x that caused WOHyperlink to generate doubly-escaped ampersands its URLs (see: <http://lists.apple.com/archives/webobjects-dev/2006/Feb/msg00324.html>). I've been using Daniel Muller's patch <http://lists.apple.com/archives/webobjects-dev/2006/Feb/msg00451.html> ever since.

Recently, I ran up against the performance limitations of this fix: A page with a few hundred links on it takes ~30 seconds to generate, 2/3 of which are spent in the patch code. So, I tweaked the patch to improve its performance, and wanted to share my results (below). Using this version, the page generation is well under one second. The performance improvement comes from in-place manipulation of the response's content, as opposed to replacing the content with a modified copy. This results in a much smaller memory footprint, which greatly reduces the time spent allocating and garbage-collecting throughout the application.

NOTE: This fix requires the use of a custom WOResponse sub-class. If the response is not an instance of this special sub-class, the older, less-efficient implementation is used. An alternative would be to use Java reflection to access to WOMessage's (protected)  _content ivar.


in your WOApplication sub-class:

    public Application() {
        _NSUtilities.setClassForName(wo.patch.WOHyperlinkPatch.class, "WOHyperlink");
    }

    /**
     *  Overridden to use WOHyperlinkPatch.AccessibleResponse so we can apply the patch more efficiently.
     */
    public WOResponse createResponseInContext( WOContext c ) {
        return new WOHyperlinkPatch.AccessibleResponse();
    }


wo.patch.WOHyperlinkPatch.java:

package wo.patch;

import com.webobjects.foundation.*;
import com.webobjects.appserver.*;
import com.webobjects.appserver._private.*;

import java.util.regex.Pattern;

public class WOHyperlinkPatch extends WOHyperlink {

    /**
     *  A WOResponse sub-class that, if used, makes the patch more efficient.
     */
    public static class AccessibleResponse extends WOResponse {
        /**
         *  Provides direct access to the content string-buffer. This allows us to fix the response content more efficiently.
         */
        public CharSequence _mutableContentString() {
            return _content;
        }
    }

    private static final String   BOZO_AMPERSAND = "&amp;amp;";
    private static final String SIMPLE_AMPERSAND = "&amp;";

    private static final Pattern PatchPattern     = Pattern.compile( "\\Q" + BOZO_AMPERSAND + "\\E" );
    private static final String  PatchReplacement = SIMPLE_AMPERSAND;


    public WOHyperlinkPatch( String aName, NSDictionary associations, WOElement template ) {
        super( aName, associations, template );
    }

    /**
     *  Overridden to correct any bozo ampersands that were appended as part of the query string.
     */
    protected void _appendQueryStringToResponse( WOResponse r, WOContext c, boolean flag ) {
        boolean isAccessible = ( r instanceof AccessibleResponse );

        CharSequence content0, content1;
        int length0, length1;

        //  Get the content (and its length) before appending the query string:

        content0 = ( isAccessible ? ((AccessibleResponse)r)._mutableContentString() : r.contentString() );
        length0  = content0.length();

        super._appendQueryStringToResponse( r, c, flag );

        //  Get the content (and its length) after appending the query string:

        content1 = ( isAccessible ? content0 : r.contentString() );
        length1  = content1.length();

        if ( length1 > length0 ) {
            String q = content1.subSequence( length0, length1 ).toString();

            if ( q.indexOf( BOZO_AMPERSAND ) != -1 ) {
                //  Correct the bozo ampersands:

                q = PatchPattern.matcher( q ).replaceAll( PatchReplacement );

                if ( isAccessible ) {
                    ((StringBuffer)content1).setLength( length0 );
                    ((StringBuffer)content1).append( q );
                } else {
                    NSLog.out.appendln( "********** WARNING: WOHyperlinkPatch is applying the inefficient patch **********" );
                    r.setContent( content0 + q );
                }
            } else if ( q.indexOf('=') != q.lastIndexOf('=')  &&  q.indexOf( SIMPLE_AMPERSAND ) > 0 ) {
                //  If the query string contains multiple name-value pairs, but only simple ampersands, this bug might have been fixed...
                NSLog.out.appendln( "********** NOTICE: WOHyperlinkPatch may be unnecessary now **********" );
            }
        }
    }
}

My apologies if there are typos in the above code -- it was a copy-paste-clean-up job.

--

Alex Johnson

Attachment: smime.p7s
Description: S/MIME cryptographic signature

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: WOHyperlink, BOZO_AMPERSAND Revisited
      • From: Galen Rhodes <email@hidden>
  • Prev by Date: Re: excludeObjectFromPropertyWithKey weird error
  • Next by Date: Running Totals
  • Previous by thread: Excel Generator
  • Next by thread: Re: WOHyperlink, BOZO_AMPERSAND Revisited
  • Index(es):
    • Date
    • Thread