/*
* Copyright 2000-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.util.rewriter;
// java.io
import java.io.Reader;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.StringTokenizer;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import org.apache.turbine.util.Log;
/**
*
* HTML Rewriter for transformer service
*
* @author <a href="mailto:mmari@ce.unipr.it">Marco Mari</a>
* @version $Id: ClipperRewriter.java,v 1.2 2004/02/23 03:18:59 jford Exp $
*/
public class ClipperRewriter extends HTMLRewriter
{
private String startElement;
private String stopElement;
private boolean foundStart = false;
private boolean foundStop = false;
private boolean nested = false;
private int nestedNumber = 0;
private int startElementNumber;
private int foundElementNumber = 0;
private String NOT_FOUND = "<br>Element not found, returning null<br>";
private String INVALID_START = "<br>Error: received null start element<br>";
private String INVALID_NUMBER =
"<br>Error: received tagNumber negative or null<br>";
/*
* Construct the Clipper Rewriter
*
*/
public ClipperRewriter()
{
}
/*
* Rewriting HTML content between startElement and stopElement
*
* @param input the HTML input stream.
* @param baseURL the base URL of the target host.
* @return the rewritten HTML output stream.
*
* @exception MalformedURLException a servlet exception.
*/
public String rewrite(Reader input, String baseURL)
throws MalformedURLException
{
this.baseURL = baseURL;
String rewrittenHTML = "";
foundStart = false;
foundStop = false;
nestedNumber = 0;
foundElementNumber = 0;
// Null startElement is invalid
if (startElement == null)
{
return INVALID_START;
}
// StartElementNumber must be positive
if (startElementNumber <= 0)
{
return INVALID_NUMBER;
}
nested = controlCoupled(startElement, stopElement);
HTMLParserAdaptor parser = new SwingParserAdaptor(this);
rewrittenHTML = parser.run(input);
if (Log.getLogger().isDebugEnabled())
{
Log.debug("Clipper rewriter: start element:" + startElement);
Log.debug("Clipper rewriter: stop element:" + stopElement);
Log.debug("Clipper rewriter: foundStart:" + foundStart);
Log.debug("Clipper rewriter: foundStop:" + foundStop);
Log.debug("Clipper rewriter: nested:" + nested);
Log.debug(
"Clipper rewriter: foundElementNumber:" + foundElementNumber);
Log.debug("Clipper rewriter: rewrittenHTML:" + rewrittenHTML);
}
if ((foundStart == false)
|| ((foundStop == false) && (stopElement != null)))
return NOT_FOUND;
else
return rewrittenHTML;
}
/*
* Returns true if all rewritten URLs should be sent back to the proxy server.
*
* @return true if all URLs are rewritten back to proxy server.
*/
public boolean proxyAllTags()
{
return true;
}
/*
* Simple Tag Events
*/
public boolean enterSimpleTagEvent(HTML.Tag tag, MutableAttributeSet attrs)
{
String attributes = attrsToString(attrs);
String tagString = tag.toString();
return checkTag(tagString, attributes, "simple");
}
/*
* Start Tag Events
*/
public boolean enterStartTagEvent(HTML.Tag tag, MutableAttributeSet attrs)
{
String attributes = attrsToString(attrs);
String tagString = tag.toString();
return checkTag(tagString, attributes, "start");
}
/*
* Exit Tag Events
*/
public boolean enterEndTagEvent(HTML.Tag tag)
{
String tagString = tag.toString();
return checkTag(tagString, null, "end");
}
/*
* Text Event
*/
public boolean enterText(char[] values, int param)
{
if ((foundStart == true)
&& (foundStop == false)
&& (stopElement != null))
return true;
else
return false;
}
/**
* Set the start element
*
* @param startElement the new start element
*/
public void setStartElement(String startElement)
{
this.startElement = startElement;
}
/**
* Set the stop element
*
* @param stopElement the new stop element
*/
public void setStopElement(String stopElement)
{
this.stopElement = stopElement;
}
/**
* Set the start element number
*
* @param startElementNumber the new start element number
*/
public void setStartElementNumber(int startElementNumber)
{
this.startElementNumber = startElementNumber;
}
/*
* Control if searched tags are coupled.
* If searched tags are coupled, we must consider nested tags, example:
* Searched: <table> and </table>
* in the page there is:
* <table>...
* <table>...
* </table>
* </table>
* We are searching for the first and fourth tag!
*/
private boolean controlCoupled(String start, String stop)
{
StringTokenizer startTok = new StringTokenizer(start);
boolean foundCoupled = false;
String token;
if (stop == null)
return false;
while (startTok.hasMoreTokens())
{
token = startTok.nextToken();
if (token.equals(stop) == true)
return true;
}
return false;
}
/*
* Convert the attributes set to a string
*/
private String attrsToString(MutableAttributeSet attrs)
{
String element = "";
if (attrs != null)
{
Enumeration en = attrs.getAttributeNames();
while (en.hasMoreElements())
{
Object attr = en.nextElement();
element =
element
+ " "
+ attr.toString()
+ "="
+ attrs.getAttribute(attr).toString();
}
return element;
}
return null;
}
/*
* Control to include or exclude the tag
*/
private boolean checkTag(String tag, String attrs, String position)
{
if (foundStart == false)
{
// Searching for start element
if ((compareTag(tag, attrs, startElement) == true)
&& ((position.equals("end") == false) || (stopElement == null)))
{
foundElementNumber = foundElementNumber + 1;
if (foundElementNumber == startElementNumber)
{
foundStart = true;
if (nested == true)
nestedNumber = nestedNumber + 1;
return true;
}
else
return false;
}
else
{
// It's not start element
return false;
}
// Searching for stop element
}
else if ((foundStop == false) && (stopElement != null))
{
if (compareTag(tag, attrs, stopElement))
{
if (nested == true)
if (position.equals("start"))
nestedNumber = nestedNumber + 1;
else if (position.equals("end"))
nestedNumber = nestedNumber - 1;
if ((nestedNumber == 0) && (position.equals("start") == false))
foundStop = true;
return true;
}
else
{
// It's not stop element
return true;
}
}
else
// Stop already found, don't include this tag
return false;
}
/*
* Control if the current tag is the searched tag with the right attributes
*/
private boolean compareTag(String tag, String attrs, String base)
{
StringTokenizer baseTok = new StringTokenizer(base);
String token;
boolean foundTag = false;
while (baseTok.hasMoreTokens())
{
token = baseTok.nextToken();
// Exact match for the tag, for the attrs it's simpler to control the index
if (token.equals(tag))
foundTag = true;
else if (attrs == null)
return false;
else if (attrs.indexOf(token) == -1)
return false;
}
if (foundTag == false)
return false;
else
{
if (Log.getLogger().isDebugEnabled())
Log.debug(
"Clipper rewriter: match between tag "
+ tag
+ ", attrs "
+ attrs
+ ", and searched: "
+ base);
return true;
}
}
}