// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.wiki; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.Iterator; import java.util.List; import util.Clock; import fitnesse.http.ResponseParser; public class ProxyPage extends CachingPage implements Serializable { private static final long serialVersionUID = 1L; public static int retrievalCount = 0; private String host; private int hostPort; private WikiPagePath realPath; public ResponseParser parser; private long lastLoadChildrenTime = 0; public ProxyPage(WikiPage original) { super(original.getName(), null); realPath = original.getPageCrawler().getFullPath(original); List<?> children = original.getChildren(); for (Iterator<?> iterator = children.iterator(); iterator.hasNext();) { ProxyPage child = new ProxyPage((WikiPage) iterator.next()); child.parent = this; this.children.put(child.getName(), child); } } protected ProxyPage(String name, WikiPage parent) { super(name, parent); } public ProxyPage(String name, WikiPage parent, String host, int port, WikiPagePath path) { super(name, parent); this.host = host; hostPort = port; realPath = path; } public static ProxyPage retrievePage(String urlString) { retrievalCount++; URL url; try { url = new URL(urlString + "?responder=proxy&type=bones"); } catch (MalformedURLException e) { throw new RuntimeException(e); } ProxyPage page = (ProxyPage) getObjectFromUrl(url); page.setTransientValues(url.getHost(), Clock.currentTimeInMillis()); int port = url.getPort(); page.setHostPort((port == -1) ? 80 : port); page.lastLoadChildrenTime = Clock.currentTimeInMillis(); return page; } protected WikiPage createChildPage(String name) { WikiPagePath childPath = realPath.copy().addNameToEnd(name); return new ProxyPage(name, this, host, getHostPort(), childPath); } protected void loadChildren() { if (cacheTime <= (Clock.currentTimeInMillis() - lastLoadChildrenTime)) { ProxyPage page = retrievePage(getThisPageUrl()); children.clear(); for (Iterator<?> iterator = page.children.values().iterator(); iterator.hasNext();) { ProxyPage child = (ProxyPage) iterator.next(); child.parent = this; children.put(child.getName(), child); } lastLoadChildrenTime = Clock.currentTimeInMillis(); } } public String getThisPageUrl() { StringBuffer url = new StringBuffer("http://"); url.append(host); url.append(":").append(getHostPort()); url.append("/").append(PathParser.render(realPath)); return url.toString(); } public boolean hasChildPage(String pageName) { if (children.containsKey(pageName)) return true; else { loadChildren(); return children.containsKey(pageName); } } public void setTransientValues(String host, long lastLoadTime) { this.host = host; lastLoadChildrenTime = lastLoadTime; for (Iterator<WikiPage> i = children.values().iterator(); i.hasNext();) { ProxyPage page = (ProxyPage) i.next(); page.setTransientValues(host, lastLoadTime); } } public String getHost() { return host; } public void setHostPort(int port) { hostPort = port; for (Iterator<WikiPage> i = children.values().iterator(); i.hasNext();) { ProxyPage page = (ProxyPage) i.next(); page.setHostPort(port); } } public int getHostPort() { return hostPort; } public PageData getMeat() { return getMeat(null); } public PageData getMeat(String versionName) { StringBuffer urlString = new StringBuffer(getThisPageUrl()); urlString.append("?responder=proxy&type=meat"); if (versionName != null) urlString.append("&version=").append(versionName); URL url; try { url = new URL(urlString.toString()); } catch (MalformedURLException e) { throw new RuntimeException(e); } PageData data = (PageData) getObjectFromUrl(url); if (data != null) data.setWikiPage(this); return data; } private static Object getObjectFromUrl(URL url) { Object obj; InputStream is = null; ObjectInputStream ois = null; try { is = url.openStream(); ois = new ObjectInputStream(is); obj = ois.readObject(); return obj; } catch (IOException e) { throw new RuntimeException("An error occured reading data from " + url, e); } catch (ClassNotFoundException e) { throw new RuntimeException("An error occured reading data from " + url, e); } finally { try { if (is != null) is.close(); if (ois != null) ois.close(); } catch (IOException e) { } } } protected PageData makePageData() { return getMeat(); } public PageData getDataVersion(String versionName) { PageData data = getMeat(versionName); if (data == null) throw new NoSuchVersionException("There is no version '" + versionName + "'"); return data; } public boolean isOpenInNewWindow() { return true; } //TODO-MdM these are not needed // We expect this to go away when we do the checkout model protected VersionInfo makeVersion() { return null; } protected void doCommit(PageData data) { } }