blob: ae41c5a764a912ee116ce3f8a0c1cee06488ec63 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.internal.webapp.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
import org.eclipse.help.internal.webapp.data.*;
public class HighlightFilter implements IFilter {
private static final String scriptPart1 = "\n<script language=\"JavaScript\">\n<!--\nvar keywords = new Array ("; //$NON-NLS-1$
private static final String scriptPart3 = ");\n-->\n</script>\n<script language=\"JavaScript\" src=\""; //$NON-NLS-1$
private static final String scriptPart5 = "advanced/highlight.js\"></script>\n"; //$NON-NLS-1$
/*
* @see IFilter#filter(HttpServletRequest, OutputStream)
*/
public OutputStream filter(HttpServletRequest req, OutputStream out) {
String uri = req.getRequestURI();
if (uri == null || !uri.endsWith("html") && !uri.endsWith("htm")) { //$NON-NLS-1$ //$NON-NLS-2$
return out;
}
if (!(UrlUtil.isIE(req) || UrlUtil.isMozilla(req))) {
return out;
}
Collection keywords = getWords(req);
if (keywords.size() == 0) {
return out;
}
keywords = removeWildCards(keywords);
keywords = encodeKeyWords(keywords);
byte[] script = createJScript(req, keywords);
if (script == null) {
return out;
}
return new FilterHTMLHeadOutputStream(out, script);
}
/**
* Creates Java Script that does highlighting
*
* @param keywords
* @return byte[]
*/
private byte[] createJScript(HttpServletRequest req, Collection keywords) {
StringBuffer buf = new StringBuffer(scriptPart1);
// append comma separated list of keywords
Iterator it = keywords.iterator();
if (!it.hasNext())
return null;
String keyword = (String) it.next();
buf.append("\"").append(keyword).append("\""); //$NON-NLS-1$ //$NON-NLS-2$
while (it.hasNext()) {
keyword = (String) it.next();
buf.append(", \"").append(keyword).append("\""); //$NON-NLS-1$ //$NON-NLS-2$
}
//
buf.append(scriptPart3);
// append "../" to get to the webapp
String path = req.getPathInfo();
if (path != null) {
for (int i; 0 <= (i = path.indexOf('/')); path = path
.substring(i + 1)) {
buf.append("../"); //$NON-NLS-1$
}
}
//
buf.append(scriptPart5);
try {
return buf.toString().getBytes("ASCII");
} catch (UnsupportedEncodingException uee) {
return new byte[0];
}
}
/**
* Extracts keywords from query that contains keywords dobule quoted and
* separated by space
*
* @return Collection of String
*/
private Collection getWords(HttpServletRequest req) {
// Collect words to hash set to eliminate duplcates
Collection tokens = new ArrayList();
String searchWord = req.getParameter("resultof"); //$NON-NLS-1$
if (searchWord == null) {
return tokens;
}
//Divide along quotation marks
StringTokenizer qTokenizer = new StringTokenizer(searchWord.trim(),
"\"", true); //$NON-NLS-1$
boolean withinQuotation = false;
String quotedString = ""; //$NON-NLS-1$
while (qTokenizer.hasMoreTokens()) {
String curToken = qTokenizer.nextToken();
if (curToken.equals("\"")) { //$NON-NLS-1$
if (!withinQuotation) {
//beginning of quoted string
quotedString = ""; //$NON-NLS-1$
} else {
//end of quoted string
tokens.add(quotedString);
}
withinQuotation = !withinQuotation;
continue;
}
if (withinQuotation) {
tokens.add(curToken);
}
}
return tokens;
}
/**
* Encodes strings inside collection for embedding in HTML source
*
* @return Collection of String
*/
private Collection encodeKeyWords(Collection col) {
if (col == null)
return col;
Collection result = new ArrayList();
for (Iterator it = col.iterator(); it.hasNext();) {
String word = (String) it.next();
int l = word.length();
if (l < 1)
continue;
result.add(UrlUtil.JavaScriptEncode(word));
}
return result;
}
/**
* Removes wildcard characters from words, by splitting words around wild
* cards
*
* @return Collection of String
*/
private Collection removeWildCards(Collection col) {
if (col == null)
return col;
// Split words into parts: before "*" and after "*"
Collection resultPass1 = new ArrayList();
for (Iterator it = col.iterator(); it.hasNext();) {
String word = (String) it.next();
int index;
while ((index = word.indexOf("*")) >= 0) { //$NON-NLS-1$
if (index > 0)
resultPass1.add(word.substring(0, index));
if (word.length() > index)
word = word.substring(index + 1);
}
if (word.length() > 0)
resultPass1.add(word);
}
// Split words into parts: before "?" and after "?"
Collection resultPass2 = new ArrayList();
for (Iterator it = resultPass1.iterator(); it.hasNext();) {
String word = (String) it.next();
int index;
while ((index = word.indexOf("?")) >= 0) { //$NON-NLS-1$
if (index > 0)
resultPass2.add(word.substring(0, index));
if (word.length() > index)
word = word.substring(index + 1);
}
if (word.length() > 0)
resultPass2.add(word);
}
return resultPass2;
}
}