001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 package lapis.tcl; 017 018 import java.io.*; 019 import java.util.*; 020 import lapisx.util.Str; 021 022 public abstract class Optimizer { 023 public static lapisx.util.Debug debug = lapisx.util.Debug.QUIET; 024 025 /** 026 * Optimize a Tcl script by commenting out any URL command 027 * that is immediately followed by another URL command 028 */ 029 public static String optimizeDeadURLs (String script) { 030 StreamTokenizer in = new StreamTokenizer (new StringReader (script)); 031 in.resetSyntax (); 032 in.wordChars (Character.MIN_VALUE, Character.MAX_VALUE); 033 in.whitespaceChars ('\r', '\r'); 034 in.whitespaceChars ('\n', '\n'); 035 036 StringWriter sout = new StringWriter (); 037 PrintWriter out = new PrintWriter (sout); 038 039 String last = null; // last command, including surrounding whitespace 040 boolean lastWasURL = false; // last command was a URL 041 042 try { 043 while (in.nextToken () != StreamTokenizer.TT_EOF) { 044 if (in.ttype == StreamTokenizer.TT_WORD) { 045 String cmd = trim (in.sval); 046 047 if (cmd.length () == 0) { 048 if (last != null) 049 last = last + in.sval + "\n"; 050 else 051 last = in.sval + "\n"; 052 } else { 053 if (isURL (cmd)) { 054 if (lastWasURL) 055 // comment out last command 056 last = "# " + last; 057 lastWasURL = true; 058 } else { 059 lastWasURL = false; 060 } 061 062 // print previous command 063 if (last != null) 064 out.print (last); 065 last = in.sval + "\n"; 066 } 067 } 068 } 069 070 if (last != null) 071 out.print (last); 072 073 out.close (); 074 return sout.toString (); 075 } catch (IOException e) { 076 debug.report (e); 077 return script; 078 } 079 } 080 081 082 /** 083 * Optimize a Tcl script by converting a form submission 084 * (URL, enter, enter, ..., submit) into a webquery command. 085 */ 086 public static String optimizeFormSubmits (String script) { 087 StreamTokenizer in = new StreamTokenizer (new StringReader (script)); 088 in.resetSyntax (); 089 in.wordChars (Character.MIN_VALUE, Character.MAX_VALUE); 090 in.whitespaceChars ('\r', '\r'); 091 in.whitespaceChars ('\n', '\n'); 092 093 StringWriter sout = new StringWriter (); 094 PrintWriter out = new PrintWriter (sout); 095 096 String formSubmission = null; 097 // current form submission, or null if not currently 098 // reading a form submission 099 100 String hrefForm = null; 101 // URL of form 102 Vector params = new Vector (); 103 // parameters of Enter commands: name, value, name, value, ... 104 105 try { 106 while (in.nextToken () != StreamTokenizer.TT_EOF) { 107 if (in.ttype == StreamTokenizer.TT_WORD) { 108 String cmd = trim (in.sval); 109 String line = in.sval + "\n"; 110 111 if (formSubmission == null) { 112 if (isURL (cmd)) { 113 formSubmission = line; 114 hrefForm = cmd; 115 params.removeAllElements (); 116 } 117 else 118 out.print (line); 119 } else { 120 if (isURL (cmd)) { 121 // Jumped to a new URL before form submission 122 // was complete. Print out partial form 123 // submission and reset for new form. 124 out.print (formSubmission); 125 formSubmission = line; 126 hrefForm = cmd; 127 params.removeAllElements (); 128 } else if (isCommand (cmd, "enter")) { 129 if (getEnterParameters (cmd, params)) 130 // Continuing form submission 131 formSubmission += in.sval + "\n"; 132 else { 133 // Can't handle this form submission 134 System.err.println ("Can't handle enter command: " + cmd); 135 out.print (formSubmission); 136 out.print (line); 137 formSubmission = null; 138 } 139 } else if (isCommand (cmd, "submit")) { 140 out.print (formSubmission); 141 out.print (line); 142 formSubmission = null; 143 144 // try { 145 // FormURL formURL = Submit.submit 146 // (new Arguments ().getFactory ().make (hrefForm), 147 148 149 // new lapis.tools.Submit () 150 // .invoke (new Arguments () 151 // .add ("href", hrefForm)); 152 153 // out.print ("webquery"); 154 // out.print (" -" + formURL.getMethod ().toLowerCase ()); 155 // out.print (" " + formURL.getAction ()); 156 157 // Hashtable defaults = formURL.getQueryHash (); 158 159 // // Print enter'ed params first 160 // for (int i = 0, n = params.size (); 161 // i < n; ++i) { 162 // Object obj = params.elementAt (i); 163 // out.print (" " + obj); 164 // if (i % 2 == 0) 165 // // it's a parameter name; delete it from 166 // // list of defaults 167 // defaults.remove (obj); 168 // } 169 170 // // Now print defaults 171 // for (Enumeration e = defaults.keys (); 172 // e.hasMoreElements (); ) { 173 // Object key = e.nextElement (); 174 // out.print (" " + key + " " + defaults.get(key)); 175 // } 176 177 // // finish command and return to start state 178 // out.println (); 179 // formSubmission = null; 180 // } catch (Exception e) { 181 // // forget trying to optimize this submission 182 // e.printStackTrace (); 183 // out.print (formSubmission); 184 // formSubmission = null; 185 // } 186 } else { 187 // Unfinished form submission, can't be optimized 188 out.print (formSubmission); 189 formSubmission = null; 190 } 191 } 192 } 193 } 194 195 if (formSubmission != null) 196 out.print (formSubmission); 197 198 out.close (); 199 return sout.toString (); 200 } catch (IOException e) { 201 debug.report (e); 202 return script; 203 } 204 } 205 206 207 208 /** 209 * Deletes trailing comment (#...) and leading and trailing whitespace 210 * from a string. 211 */ 212 static String trim (String line) { 213 int comment = line.lastIndexOf ('#'); 214 if (comment >= 0) 215 line = line.substring (0, comment); 216 return line.trim (); 217 } 218 219 /** 220 * Tests whether command is a URL. 221 */ 222 static boolean isURL (String cmd) { 223 return cmd.startsWith ("http:") 224 || cmd.startsWith ("ftp:") 225 || cmd.startsWith ("file:") 226 || cmd.startsWith ("systemresource:"); 227 } 228 229 static boolean isCommand (String cmd, String cmdName) { 230 return cmd.startsWith (cmdName) 231 && (cmd.length() == cmdName.length() 232 || Character.isWhitespace (cmd.charAt (cmdName.length()))); 233 } 234 235 static boolean getEnterParameters (String cmd, Vector params) { 236 String args = Str.after (cmd, " ").trim (); 237 238 String fieldArg = Str.before (args, " ").trim (); 239 if (!fieldArg.toLowerCase ().startsWith ("Field.") 240 || fieldArg.indexOf (" ") != -1) 241 // this enter command uses a pattern more complicated than 242 // Field.foo -- we can't handle it 243 return false; 244 String fieldName = fieldArg.substring (6); 245 246 String valueArg = Str.after (args, " ").trim (); 247 248 params.addElement (fieldName); 249 params.addElement (valueArg); 250 return true; 251 } 252 253 } 254