001: /*
002: * MapPage.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 1999-2000 Sun Microsystems, Inc.
007: *
008: * Sun Public License Notice
009: *
010: * The contents of this file are subject to the Sun Public License Version
011: * 1.0 (the "License"). You may not use this file except in compliance with
012: * the License. A copy of the License is included as the file "license.terms",
013: * and also available at http://www.sun.com/
014: *
015: * The Original Code is from:
016: * Brazil project web application Framework release 1.1.
017: * The Initial Developer of the Original Code is: suhler.
018: * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
019: * All Rights Reserved.
020: *
021: * Contributor(s): cstevens, suhler.
022: *
023: * Version: 1.18
024: * Created by suhler on 99/06/28
025: * Last modified by suhler on 00/12/27 12:11:48
026: */
027:
028: package sunlabs.brazil.handler;
029:
030: import java.util.Hashtable;
031: import java.util.Vector;
032: import java.util.Enumeration;
033: import sunlabs.brazil.util.regexp.Regexp;
034:
035: /**
036: * Utility class to rewrite links inside of web pages so they appear to
037: * come from a different site.
038: *
039: * @author Stephen Uhler
040: * @version 1.10, 05/25/99
041: */
042:
043: public class MapPage {
044: /**
045: * Initialized to all tag/attribute pairs whose attribute values are
046: * considered for rewriting.
047: */
048: public Hashtable tagMap; // tag attributes to map
049: public Hashtable urlMap; // mapping table
050: public Vector patternMap; // mapping table for glob patterns
051: public String prefix; // prefix to prepend onto mapped url's
052: // that start with "/"
053: public static boolean log = false; // enable/disable diagnostics
054: public int count; // number of tags rewritten
055:
056: /**
057: * Create a site mapper. The following table maps all the entity/attribute
058: * combinations that are (or could be) URL's to (possibly) rewrite.
059: * @param prefix Every link starting with "/" has the leading
060: * slash replaced by <code>prefix</code>. If prefix is
061: * <i>null</i>, then only fully qualified url's are
062: * considered for rewriting.
063: */
064:
065: public MapPage(String prefix) {
066: this .prefix = prefix;
067: urlMap = null;
068: patternMap = new Vector();
069: count = 0;
070: tagMap = new Hashtable(19);
071: tagMap.put("a", "href");
072: tagMap.put("applet", "codebase");
073: tagMap.put("area", "href");
074: tagMap.put("base", "href");
075: tagMap.put("body", "background");
076: tagMap.put("embed", "src");
077: tagMap.put("form", "action");
078: tagMap.put("frame", "src");
079: tagMap.put("img", "src");
080: tagMap.put("layer", "src");
081: tagMap.put("link", "href");
082: tagMap.put("object", "codebase");
083: tagMap.put("param", "value"); // Not sure about this one
084: tagMap.put("td", "background");
085: tagMap.put("th", "background");
086: tagMap.put("input", "src"); // image input items?
087: tagMap.put("script", "src"); // ???
088: log("prefix: " + prefix);
089: }
090:
091: /**
092: * Change the prefix that will replace the leading "/" in a URL.
093: */
094:
095: public void setPrefix(String prefix) {
096: this .prefix = prefix;
097: log("prefix: " + prefix);
098: }
099:
100: /**
101: * add a tag/attribute pair to the rewrite list.
102: * If the attribute is null, remove the tag.
103: */
104:
105: public void addTag(String name, String attribute) {
106: if (attribute == null) {
107: tagMap.remove(name);
108: } else {
109: tagMap.put(name.toLowerCase(), attribute.toLowerCase());
110: }
111: }
112:
113: /**
114: * Set the map table for cross-linked sites.
115: * Foreach key in the table that matches a URL, replace the key
116: * portion of the url with the key's value.
117: */
118:
119: public void setMap(Hashtable map) {
120: urlMap = map;
121: }
122:
123: /**
124: * Add or remove an item to the map table
125: * @param name The prefix of the url to match
126: * @param value The prefix to replace it with. If null,
127: * remove the prefix
128: */
129:
130: public void addMapEntry(String name, String value) {
131: if (value == null && urlMap != null) {
132: urlMap.remove(name);
133: return;
134: } else if (urlMap == null) {
135: urlMap = new Hashtable();
136: }
137: urlMap.put(name, value);
138: }
139:
140: /**
141: * Add or remove an item to the pattern table
142: * @param pattern The prefix pattern of the url to match
143: * Full tcl8.0-style regexps are supported
144: * @param replacement The prefix to replace it with. If null,
145: * remove the prefix. \n's are replaced by the
146: * corrosponding sub-matches in the name
147: * <P>
148: * Patterns are stored in a vector, with each pattern taking 3
149: * concecutive elements: the pattern, the replacement rule, and
150: * the compiled expression. This way they are searched in order.
151: * Sample usage:
152: * http://www.([^.]*).com/ /site/\1/
153: * will replace the url: http://www.foo.com/a/b.html with
154: * /site/foo/a/b.html
155: */
156:
157: public void addPatternEntry(String pattern, String replacement) {
158: if (!pattern.startsWith("^")) {
159: pattern = "^" + pattern;
160: }
161: // System.out.println("Adding pattern: " + pattern + " (" + replacement + ")");
162: int index = patternMap.indexOf(pattern);
163: if (index > 0 && replacement == null) {
164: patternMap.removeElementAt(index);
165: patternMap.removeElementAt(index);
166: patternMap.removeElementAt(index);
167: } else if (index > 0) {
168: patternMap.setElementAt(replacement, ++index);
169: patternMap.setElementAt(new Regexp(pattern), ++index);
170: } else if (replacement != null) {
171: patternMap.addElement(pattern);
172: patternMap.addElement(replacement);
173: patternMap.addElement(new Regexp(pattern));
174: }
175: }
176:
177: /**
178: * How many tags have been mapped?
179: */
180:
181: public int mapCount() {
182: return count;
183: }
184:
185: /**
186: * Rewrite all the url's in this document. This is accomplished
187: * via repeated calls to {@link #convertString}.
188: *
189: * @param content The HTML to be processed.
190: * @result The smae HTML, will all URL's rewritten.
191: * URL's starting with "/" have the "/" replaced
192: * with the prefix. All others are re-written based
193: * on the supplied mapping tables.
194: */
195:
196: public String convertHtml(String content) {
197: Hashtable h; // the tag parameters
198: HtmlRewriter hr = new HtmlRewriter(content);
199: while (hr.nextTag()) {
200: String tag = hr.getTag().toLowerCase();
201: String param = (String) tagMap.get(tag);
202: if (param == null) {
203: continue;
204: }
205: String value = hr.get(param);
206: if (value == null) {
207: continue;
208: }
209: String fixed = convertString(value);
210: if (fixed != null) {
211: hr.put(param, fixed);
212: }
213: }
214: return hr.toString();
215: }
216:
217: /**
218: * Rewrite a url inside a tag parameter.
219: *
220: * @param fix The value of the tag to be rewritten (fixed)
221: * @return null of the existing value is OK,
222: * otherwise the new value is returned
223: */
224:
225: public String convertString(String fix) {
226: if (fix.startsWith("/")) {
227: if (prefix == null) {
228: return null;
229: }
230: count++;
231: String result = prefix + fix.substring(1);
232: log(fix + " -> " + result);
233: return result;
234: }
235: if (fix.startsWith("http://") && urlMap != null) {
236: if (fix.indexOf("/", 7) == -1) {
237: log(" adding missing /");
238: fix += "/";
239: }
240: Enumeration e = urlMap.keys();
241: while (e.hasMoreElements()) {
242: String match = (String) e.nextElement();
243: log(" " + fix + " <?> " + match);
244: if (fix.startsWith(match)) {
245: count++;
246: String result = urlMap.get(match)
247: + fix.substring(match.length());
248: log(fix + " -> " + result);
249: return result;
250: }
251: }
252: }
253:
254: /*
255: * check the regexp patterns
256: */
257:
258: for (int i = 0; i < patternMap.size(); i += 3) {
259: Regexp exp = (Regexp) patternMap.elementAt(i + 2);
260: String replace = exp.sub(fix, (String) patternMap
261: .elementAt(i + 1));
262: if (replace != null) {
263: count++;
264: return replace;
265: }
266: }
267: log("No mapping for (" + fix + ")");
268: return null;
269: }
270:
271: /**
272: * diagnostic output
273: */
274:
275: public void log(String message) {
276: if (log) {
277: System.out.println("MapPage: " + message);
278: }
279: }
280: }
|