// MirrorFrame.java
// $Id: MirrorFrame.java,v 1.13 2004/02/12 10:49:20 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1998
// Please first read the full copyright statement in file COPYRIGHT.html
package org.w3c.jigsaw.proxy ;
import java.net.URL;
import java.io.IOException;
import org.w3c.www.http.HTTP;
import org.w3c.tools.resources.Attribute;
import org.w3c.tools.resources.AttributeHolder;
import org.w3c.tools.resources.AttributeRegistry;
import org.w3c.tools.resources.BooleanAttribute;
import org.w3c.tools.resources.LookupResult;
import org.w3c.tools.resources.LookupState;
import org.w3c.tools.resources.ProtocolException;
import org.w3c.tools.resources.Resource;
import org.w3c.tools.resources.ResourceFrame;
import org.w3c.tools.resources.StringAttribute;
import org.w3c.jigsaw.http.HTTPException;
import org.w3c.jigsaw.http.Reply;
import org.w3c.jigsaw.http.Request;
import org.w3c.jigsaw.frames.HTTPFrame;
public class MirrorFrame extends ForwardFrame {
/**
* Attribute index - The site we are mirroring.
*/
protected static int ATTR_MIRRORS = -1;
/**
* Attribute index - Do we mirror from root or relative
*/
protected static int ATTR_PARTIAL = -1;
static {
Class c = null;
Attribute a = null;
try {
c = Class.forName("org.w3c.jigsaw.proxy.MirrorFrame");
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
// Register the mirrored site attribute:
a = new StringAttribute("mirrors"
, null
, Attribute.EDITABLE);
ATTR_MIRRORS = AttributeRegistry.registerAttribute(c, a);
// Do we allow sub mirroring (aka parts of the site)
// and not from root
a = new BooleanAttribute("partial"
, Boolean.FALSE
, Attribute.EDITABLE);
ATTR_PARTIAL = AttributeRegistry.registerAttribute(c, a);
}
protected URL mirrors = null;
public static final String MIRROR_PATH = "MIRROR_PATH";
/**
* Get the mirrors site attribute value.
* @return The String encoded URL of the site we are mirroring here.
*/
public String getMirrors() {
return getString(ATTR_MIRRORS, null);
}
/**
* Get the mirrors site attribute value.
* @return The String encoded URL of the site we are mirroring here.
*/
public boolean isPartialMirroring() {
return getBoolean(ATTR_PARTIAL, false);
}
/**
* Catch assignment to the mirror attribute, to update our cached URL.
* @param idx The slot to set.
* @param value It's new value.
*/
public void setValue(int idx, Object value) {
super.setValue(idx, value);
if ( idx == ATTR_MIRRORS ) {
try {
mirrors = new URL(getMirrors());
} catch (Exception ex) {
mirrors = null;
}
}
}
/**
* @param request the incomming request
* @param rep the client reply
* @return A Reply instance
* @exception HTTPException if processing the request failed.
* @exception IOException if an IO error occurs.
*/
protected Reply dupReply(Request request
, org.w3c.www.protocol.http.Reply rep)
throws HTTPException, IOException
{
Reply reply = super.dupReply(request, rep);
// Tweak redirections ! Wow this is getting real nifty :-)
switch(reply.getStatus()) {
case HTTP.MOVED_PERMANENTLY:
case HTTP.TEMPORARY_REDIRECT:
case HTTP.FOUND:
case HTTP.SEE_OTHER:
// Have fun !
String location = rep.getLocation();
if ((mirrors != null) && (location != null)) {
try {
URL uloc = new URL(request.getURL(), location);
URL loc = getURL(request);
URL fake = null;
if (isPartialMirroring()) {
fake = new URL(request.getURL().getProtocol()
, loc.getHost()
, loc.getPort()
, getURLPath()+uloc.getFile());
} else if (location.startsWith(mirrors.toString())) {
fake = new URL(request.getURL().getProtocol()
, loc.getHost()
, loc.getPort()
, uloc.getFile());
} else {
fake = uloc;
}
if (fake != null) {
reply.setLocation(fake);
}
} catch (Exception ex) {
}
}
}
return reply;
}
/**
* @param request the incomming request
* @return A client Request instance.
* @exception HTTPException if processing the request failed.
* @exception IOException if an IO error occurs.
*/
protected org.w3c.www.protocol.http.Request dupRequest(Request request)
throws HTTPException, IOException
{
org.w3c.www.protocol.http.Request req = super.dupRequest(request);
// Tweak the URL :-)
if (isPartialMirroring()) {
String requrl = request.getURL().getFile();
String respath = getURLPath();
if (requrl.startsWith(respath)) {
String nurl = requrl.substring(respath.length());
req.setURL(new URL(mirrors, nurl));
} else {
req.setURL(new URL(mirrors, requrl));
}
} else {
req.setURL(new URL(mirrors, request.getURL().getFile()));
}
return req;
}
/**
* Lookup for a mirrored resource.
* @param ls The current lookup state
* @param lr The result
* @return true if lookup is done.
* @exception org.w3c.tools.resources.ProtocolException If an error
* relative to the protocol occurs
*/
public boolean lookupOther(LookupState ls, LookupResult lr)
throws org.w3c.tools.resources.ProtocolException
{
// Get the full URL from the request:
Request request = (Request) ls.getRequest();
URL url = request.getURL();
if ( ls.isInternal() )
return super.lookupOther(ls, lr);
if ( mirrors != null ) {
request.setProxy(true);
lr.setTarget(this.getResource().getResourceReference());
return true;
}
// Emit a not found:
Reply error = request.makeReply(HTTP.NOT_FOUND);
if (request.getMethod().equals("GET"))
error.setContent("Target resource not found.");
lr.setTarget(null);
lr.setReply(error);
return true;
}
public void initialize(Object values[]) {
super.initialize(values);
String strmirrors = getMirrors();
try {
mirrors = new URL(strmirrors);
} catch (Exception ex) {
mirrors = null;
}
}
}