/*
* This file is part of the Wayback archival access software
* (http://archive-access.sourceforge.net/projects/wayback/).
*
* Licensed to the Internet Archive (IA) by one or more individual
* contributors.
*
* The IA licenses this file to You 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.archive.wayback.memento;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
import java.util.TimeZone;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.archive.wayback.ReplayRenderer;
import org.archive.wayback.ResultURIConverter;
import org.archive.wayback.archivalurl.ArchivalUrlResultURIConverter;
import org.archive.wayback.core.CaptureSearchResult;
import org.archive.wayback.core.CaptureSearchResults;
import org.archive.wayback.core.Resource;
import org.archive.wayback.core.WaybackRequest;
import org.archive.wayback.exception.BadContentException;
import org.archive.wayback.exception.WaybackException;
import org.archive.wayback.replay.HttpHeaderProcessor;
import org.archive.wayback.replay.TextReplayRenderer;
import org.archive.wayback.replay.ReplayRendererDecorator;
/**
* @author brad
*
*/
public class MementoReplayRendererDecorator extends ReplayRendererDecorator {
public MementoReplayRendererDecorator() {
super();
}
/**
* @param decorated
* @param httpHeaderProcessor
*/
public MementoReplayRendererDecorator(ReplayRenderer decorated) {
super(decorated);
}
@Override
public void renderResource(HttpServletRequest httpRequest,
HttpServletResponse httpResponse, WaybackRequest wbRequest,
CaptureSearchResult result, Resource resource,
ResultURIConverter uriConverter, CaptureSearchResults results)
throws ServletException, IOException, WaybackException {
// add Memento headers:
// UIResults results = UIResults.extractCaptureQuery(request);
// WaybackRequest wbRequest = results.getWbRequest();
// CaptureSearchResults cResults = results.getCaptureResults();
// CaptureSearchResult res = cResults.getClosest();
String u = wbRequest.getRequestUrl();
SimpleDateFormat httpformatterl = new SimpleDateFormat(
"E, dd MMM yyyy HH:mm:ss z");
TimeZone tzo = TimeZone.getTimeZone("GMT");
httpformatterl.setTimeZone(tzo);
SimpleDateFormat formatterk = new SimpleDateFormat("yyyyMMddHHmmss");
formatterk.setTimeZone(tzo);
Properties apProps = wbRequest.getAccessPoint().getConfigs();
Date closestDate = result.getCaptureDate();
String uriPrefix = wbRequest.getAccessPoint().getReplayPrefix();
String agguri = apProps.getProperty("aggregationPrefix")
+ "timebundle/" + u;
String timemap = " , <"
+ apProps.getProperty("aggregationPrefix")
+ "timemap/link/" + u
+ ">;rel=\"timemap\"; type=\"application/link-format\"";
String timegate = ",<" + uriPrefix + "timegate/" + u
+ ">;rel=\"timegate\"";
Date f = results.getFirstResultDate();
Date l = results.getLastResultDate();
StringBuffer sb = new StringBuffer();
httpResponse.setHeader("Memento-Datetime",
httpformatterl.format(result.getCaptureDate()));
String memento = ",<" + uriPrefix + formatterk.format(closestDate)
+ "/" + u + ">;rel=\"memento\"; datetime=\""
+ httpformatterl.format(closestDate) + "\"";
String mfl = null;
if ((closestDate.equals(f)) && closestDate.equals(l)) {
mfl = ", <"
+ uriPrefix
+ formatterk.format(f)
+ "/"
+ u
+ ">;rel=\"first last memento\"; datetime=\""
+ httpformatterl.format(f) + "\"";
} else if (closestDate.equals(f)) {
mfl = ", <" + uriPrefix + formatterk.format(f) + "/" + u
+ ">;rel=\"first memento\"; datetime=\""
+ httpformatterl.format(f) + "\"";
mfl = mfl + ", <" + uriPrefix + formatterk.format(l) + "/" + u
+ ">;rel=\"last memento\"; datetime=\""
+ httpformatterl.format(l) + "\"";
} else if (closestDate.equals(l)) {
mfl = ", <" + uriPrefix + formatterk.format(l) + "/" + u
+ ">;rel=\"last memento\"; datetime=\""
+ httpformatterl.format(l) + "\"";
mfl = mfl + ", <" + uriPrefix + formatterk.format(f) + "/" + u
+ ">;rel=\"first memento\"; datetime=\""
+ httpformatterl.format(f) + "\"";
} else {
mfl = memento;
mfl = mfl + ", <" + uriPrefix + formatterk.format(l) + "/" + u
+ ">;rel=\"last memento\"; datetime=\""
+ httpformatterl.format(l) + "\"";
mfl = mfl + ", <" + uriPrefix + formatterk.format(f) + "/" + u
+ ">;rel=\"first memento\"; datetime=\""
+ httpformatterl.format(f) + "\"";
}
sb = new StringBuffer(mfl);
// calculate closest values for link header
CaptureSearchResult closestleft = null;
CaptureSearchResult closestright = null;
long rclosestDistance = 0;
long lclosestDistance = 0;
CaptureSearchResult cur = null;
long wantTime = closestDate.getTime();
Iterator<CaptureSearchResult> itr = results.iterator();
while (itr.hasNext()) {
cur = itr.next();
cur.getCaptureDate();
long curDistance = cur.getCaptureDate().getTime() - wantTime;
// == 0 skip
if (curDistance > 0) {
if ((closestright == null)
|| (Math.abs(curDistance) < Math
.abs(rclosestDistance))) {
closestright = cur;
rclosestDistance = Math.abs(curDistance);
}
}
if (curDistance < 0) {
if ((closestleft == null)
|| (Math.abs(curDistance) < Math
.abs(lclosestDistance))) {
closestleft = cur;
lclosestDistance = Math.abs(curDistance);
}
}
}
if (closestleft != null) {
if (!(closestleft.getCaptureDate().equals(f))) {
sb.append(", <"
+ uriPrefix
+ formatterk.format(closestleft.getCaptureDate())
+ "/"
+ u
+ ">;rel=\"prev memento\"; datetime=\""
+ httpformatterl.format(closestleft
.getCaptureDate()) + "\"");
} else {
int m_index = sb.lastIndexOf("\"first memento\"");
sb.insert(m_index + 1, "prev ");
}
}
if (closestright != null) {
if (!(closestright.getCaptureDate().equals(l))) {
sb.append(", <"
+ uriPrefix
+ formatterk.format(closestright.getCaptureDate())
+ "/"
+ u
+ ">;rel=\"next memento\"; datetime=\""
+ httpformatterl.format(closestright
.getCaptureDate()) + "\"");
} else {
int m_index = sb.lastIndexOf("\"last memento\"");
sb.insert(m_index + 1, "next ");
}
}
String origlink = ", <" + u + ">;rel=\"original\"";
httpResponse.setHeader("Link", "<" + agguri + ">;rel=\"timebundle\""
+ origlink + sb.toString() + timemap + timegate);
decorated.renderResource(httpRequest, httpResponse, wbRequest, result,
resource, uriConverter, results);
}
}