/* * [HttpParser.java] * * Summary: parse an http file into tokens, e.g. WireSharp dump. * * Copyright: (c) 2004-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2010-02-10 initial version. */ package com.mindprod.jprep; import com.mindprod.common18.ST; import com.mindprod.jtokens.NL; import com.mindprod.jtokens.Operator; import com.mindprod.jtokens.Space; import com.mindprod.jtokens.Start; import com.mindprod.jtokens.Stop; import com.mindprod.jtokens.Token; import com.mindprod.jtokens.http.DomainToken; import com.mindprod.jtokens.http.HttpKey; import com.mindprod.jtokens.http.HttpToken; import java.util.ArrayList; import java.util.regex.Pattern; /** * parse an http file into tokens, e.g. WireSharp dump. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2010-02-10 initial version. * @since 2010-02-10 */ // TODO: parse stuff after blank line as HTML class HttpParser { /** * list of tokens we have parsed out. */ private static final ArrayList tokens = new ArrayList<>( 50000 ); /** * used to split document into lines */ private static final Pattern LINE_SPLITTER = Pattern.compile( "\\r\\n" ); /** * generate tokens for a field:value * * @param line the line in the file * @param colonPlace index of first colon in the line */ private static void httpColonValue( final String line, final int colonPlace ) { final String key = line.substring( 0, colonPlace ).trim(); final String value = line.substring( colonPlace + 1 ).trim(); tokens.add( new HttpKey( key ) ); tokens.add( new Operator( ":" ) ); tokens.add( new Space() ); if ( key.equals( "Host" ) ) { tokens.add( new DomainToken( value ) ); } else { tokens.add( new HttpToken( value ) ); } } /** * generate tokens for a GET/PUT line * * @param line the line in the file * @param firstWord the first word of the line. */ private static void httpLine( final String line, final String firstWord ) { tokens.add( new HttpKey( firstWord ) ); tokens.add( new Space() ); tokens.add( new HttpToken( ST.chopLeadingString( line, firstWord ).trim() ) ); } /** * get rid of leading and trailing NLs tokens. It is easier to handle it later than during parsing. */ private static void trimNLs() { // remove leading NLs. while ( tokens.size() > 0 && ( tokens.get( 0 ) instanceof NL ) ) { tokens.remove( 0 ); } // remove trailing NLs int count; while ( ( count = tokens.size() ) > 0 && ( tokens.get( count - 1 ) instanceof NL ) ) { tokens.remove( count - 1 ); } // we don't need an NL at either beginning or end // insert at the beginning tokens.add( 0, new Start( "
" ) );
        // add to end
        tokens.add( new Stop( "
" ) ); } /** * Parse program and leave a list of Tokens in tokens ArrayList. * This is so simple, we don't need a finite state automaton * * @param program the text we are going parse and render. * * @return an array of tokens representing the text and how it will be rendered. */ public static Token[] parse( String program ) { tokens.clear(); // split into lines: String[] lines = LINE_SPLITTER.split( program ); for ( String line : lines ) { final String firstWord = ST.firstWord( line ); int colonPlace = line.indexOf( ':' ); if ( line.trim().length() == 0 ) { // do nothing, empty line. } else if ( firstWord.equalsIgnoreCase( "GET" ) || firstWord.equalsIgnoreCase( "POST" ) || firstWord.equalsIgnoreCase( "HEAD" ) || firstWord.equalsIgnoreCase( "PUT" ) ) { httpLine( line, firstWord ); } else if ( colonPlace >= 0 ) { // ideally should parse message part after first blank line as HTML httpColonValue( line, colonPlace ); } else { // not in form key:value, possible HTTP message tokens.add( new HttpToken( ST.trimTrailing( line, ' ' ) ) ); } tokens.add( new NL() ); } // end for // tidy up the list of tokens. trimNLs(); // covert to vanilla array for even more efficient use in the // final Applet. Token[] pruned = tokens.toArray( new Token[ tokens.size() ] ); tokens.clear(); return pruned; } }