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