package org.cdlib.xtf.servletBase;
/*
* Copyright (c) 2005, Regents of the University of California
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the University of California nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Acknowledgements:
*
* A significant amount of new and/or modified code in this module
* was made possible by a grant from the Andrew W. Mellon Foundation,
* as part of the Melvyl Recommender Project.
*/
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.saxon.event.ProxyReceiver;
import net.sf.saxon.event.Receiver;
import net.sf.saxon.om.NamePool;
import net.sf.saxon.trans.XPathException;
/**
* If session data has been established, this class takes care of adding the
* session ID to URLs output by a Saxon transformation.
*/
public class SessionURLRewriter extends ProxyReceiver
{
private Pattern encodeURLPattern;
private HttpServletRequest httpRequest;
private HttpServletResponse httpResponse;
private NamePool namePool;
private String elementName;
/**
* Construct the URL rewriter, recording a reference to the receiver
* that will get the data, and the HTTP servlet response we'll use to
* get session info and to rewrite URLs.
*/
SessionURLRewriter(Receiver underlyingReceiver, Pattern encodeURLPattern,
HttpServletRequest httpRequest,
HttpServletResponse httpResponse)
{
setUnderlyingReceiver(underlyingReceiver);
this.encodeURLPattern = encodeURLPattern;
this.httpRequest = httpRequest;
this.httpResponse = httpResponse;
}
/**
* Called when an element begins. We simply record the name for later
* reference.
*/
public void startElement(int nameCode, int typeCode, int locationId,
int properties)
throws XPathException
{
elementName = getLocalName(nameCode);
super.startElement(nameCode, typeCode, locationId, properties);
}
/**
* Called when an attribute is output. If it needs a session ID added,
* we do so here.
*/
public void attribute(int nameCode, int typeCode, CharSequence value,
int locationId, int properties)
throws XPathException
{
// Is this an attribute we want to edit? Right now, we try to be
// conservative:
//
// (1) "href" attribute of a <a> element;
// (2) "action" attribute of a <form> element;
// (3) "src" attribute of a <frame> element.
//
String attrName = getLocalName(nameCode);
if (!(elementName.equals("a") &&
attrName.equals("href")) &&
!(elementName.equals("form") &&
attrName.equals("action")) &&
!(elementName.equals("frame") &&
attrName.equals("src")))
{
super.attribute(nameCode, typeCode, value, locationId, properties);
return;
}
// If there's no session data, then rewriting is never necesssary.
HttpSession session = httpRequest.getSession(false); // don't create
if (session == null) {
super.attribute(nameCode, typeCode, value, locationId, properties);
return;
}
// If the URL doesn't match the pattern, don't rewrite it.
String strVal = value.toString();
if (!encodeURLPattern.matcher(strVal).matches()) {
super.attribute(nameCode, typeCode, value, locationId, properties);
return;
}
// See if the servlet container wants to map this URL to add a session ID.
String mapped = httpResponse.encodeURL(strVal);
if (!mapped.equals(value)) {
super.attribute(nameCode, typeCode, mapped, locationId, properties);
return;
}
// No match. Leave the URL unchanged.
super.attribute(nameCode, typeCode, value, locationId, properties);
} // attribute()
/** Get the local name corresponding to the given namecode */
private String getLocalName(int nameCode) {
if (namePool == null)
namePool = getNamePool();
return namePool.getLocalName(nameCode);
}
} // class SessionURLRewriter