/*
 * Copyright (c) 2010-2013 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.emf.cdo.server;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;
import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
import org.eclipse.emf.cdo.common.revision.CDORevisionUtil.AllRevisionsDumper;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision;
import org.eclipse.emf.cdo.spi.server.InternalLockManager;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalSession;
import org.eclipse.emf.cdo.spi.server.InternalView;

import org.eclipse.net4j.util.HexUtil;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.concurrent.Worker;
import org.eclipse.net4j.util.container.ContainerEventAdapter;
import org.eclipse.net4j.util.container.IContainer;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.container.IPluginContainer;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.net4j.util.io.IOUtil;

import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * A simple HTTP server that web browsers can connect to in order to render internal server data for debugging purposes.
 * <p>
 * Actual content is contributed through pluggable {@link CDOServerBrowser.Page pages}.
 * <p>
 * <b>Note:</b> Don't use this server in production, it's unsecure and does not perform or scale!
 *
 * @author Eike Stepper
 * @since 4.0
 */
public class CDOServerBrowser extends Worker
{
  private static final String REQUEST_PREFIX = "GET ";

  private static final String REQUEST_SUFFIX = " HTTP/1.1";

  private ThreadLocal<Map<String, String>> params = new InheritableThreadLocal<Map<String, String>>()
  {
    @Override
    protected Map<String, String> initialValue()
    {
      return new HashMap<String, String>();
    }
  };

  private int port = 7777;

  private ServerSocket serverSocket;

  private Map<String, InternalRepository> repositories;

  private List<Page> pages = new ArrayList<Page>();

  public CDOServerBrowser(Map<String, InternalRepository> repositories)
  {
    this.repositories = repositories;
    setDaemon(true);
  }

  public Map<String, InternalRepository> getRepositories()
  {
    return repositories;
  }

  public int getPort()
  {
    return port;
  }

  public void setPort(int port)
  {
    this.port = port;
  }

  @Override
  protected void work(WorkContext context) throws Exception
  {
    Socket socket = null;

    try
    {
      socket = serverSocket.accept();
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      OutputStream out = new BufferedOutputStream(socket.getOutputStream());
      PrintStream pout = new PrintStream(out);
      printHeader(pout);

      String line;
      while ((line = in.readLine()) != null)
      {
        if (line.startsWith(REQUEST_PREFIX) && line.endsWith(REQUEST_SUFFIX))
        {
          String request = line.substring(REQUEST_PREFIX.length(), line.length() - REQUEST_SUFFIX.length()).trim();
          String resource = request;
          String params = "";
          int pos = request.indexOf('?');
          if (pos != -1)
          {
            resource = request.substring(0, pos);
            params = request.substring(pos + 1);
          }

          initParams(params);
          if ("/".equals(resource))
          {
            showMenu(pout);
          }
          else
          {
            String pageName = resource.substring(1);
            for (Page page : pages)
            {
              if (page.getName().equals(pageName))
              {
                showPage(pout, page);
              }
            }
          }
        }

        out.flush();
        return;
      }
    }
    catch (Exception ex)
    {
      if (isActive())
      {
        ex.printStackTrace();
      }
    }
    finally
    {
      params.remove();
      if (socket != null)
      {
        socket.close();
      }
    }
  }

  protected void initParams(String params)
  {
    Map<String, String> map = this.params.get();
    for (String param : params.split("&"))
    {
      if (param.length() != 0)
      {
        String[] keyValue = param.split("=");
        map.put(keyValue[0], keyValue[1]);
      }
    }
  }

  protected void clearParams()
  {
    Map<String, String> map = params.get();
    map.clear();
  }

  public void removeParam(String key)
  {
    Map<String, String> map = params.get();
    map.remove(key);
  }

  public String getParam(String key)
  {
    Map<String, String> map = params.get();
    return map.get(key);
  }

  public String href(String label, String resource, String... params)
  {
    Map<String, String> map = new HashMap<String, String>(this.params.get());
    for (int i = 0; i < params.length;)
    {
      map.put(params[i++], params[i++]);
    }

    List<String> list = new ArrayList<String>(map.keySet());
    Collections.sort(list);

    StringBuilder builder = new StringBuilder();
    for (String key : list)
    {
      String value = map.get(key);
      if (value != null)
      {
        if (builder.length() != 0)
        {
          builder.append("&");
        }

        builder.append(key);
        builder.append("=");
        builder.append(value);
      }
    }

    return "<a href=\"/" + escape(resource) + "?" + escape(builder.toString()) + "\">" + escape(label) + "</a>";
  }

  public String escape(String raw)
  {
    if (raw == null)
    {
      return "null";
    }

    return raw.replace("<", "&lt;");
  }

  protected void printHeader(PrintStream pout)
  {
    pout.print("HTTP/1.1 200 OK\r\n");
    pout.print("Content-Type: text/html\r\n");
    pout.print("Date: " + new Date() + "\r\n");
    pout.print("Server: DBBrowser 3.0\r\n");
    pout.print("\r\n");
  }

  protected void showMenu(PrintStream pout)
  {
    clearParams();
    pout.print("<h1>CDO Server Browser 4.0</h1><hr>\r\n");

    for (Page page : pages)
    {
      pout.println("<h3>" + href(page.getLabel(), page.getName()) + "</h3>");
    }
  }

  protected void showPage(PrintStream pout, Page page)
  {
    String repo = getParam("repo");

    List<String> repoNames = new ArrayList<String>(getRepositoryNames());
    Collections.sort(repoNames);

    pout.print("<h3><a href=\"/\">" + page.getLabel() + "</a>:&nbsp;&nbsp;");
    for (String repoName : repoNames)
    {
      InternalRepository repository = getRepository(repoName);
      if (!page.canDisplay(repository))
      {
        continue;
      }

      if (repo == null)
      {
        repo = repoName;
      }

      if (repoName.equals(repo))
      {
        pout.print("<b>" + escape(repoName) + "</b>&nbsp;&nbsp;");
      }
      else
      {
        pout.print(href(repoName, page.getName(), "repo", repoName) + "&nbsp;&nbsp;");
      }
    }

    pout.print("</h3>");

    InternalRepository repository = getRepository(repo);
    if (repository != null)
    {
      pout.print("<p>\r\n");

      InternalSession session = repository.getSessionManager().openSession(null);
      StoreThreadLocal.setSession(session);

      try
      {
        page.display(this, repository, pout);
      }
      finally
      {
        StoreThreadLocal.release();
        session.close();
      }
    }
  }

  protected Set<String> getRepositoryNames()
  {
    return repositories.keySet();
  }

  protected InternalRepository getRepository(String name)
  {
    return repositories.get(name);
  }

  @Override
  protected String getThreadName()
  {
    return "CDOServerBrowser";
  }

  protected void initPages(List<Page> pages)
  {
    pages.add(new PackagesPage());
    pages.add(new LocksPage());
    pages.add(new RevisionsPage.FromCache());
    pages.add(new RevisionsPage.FromStore());
    pages.add(new LobsPage());
    pages.add(new HistoryPage());

    IManagedContainer container = getPagesContainer();
    for (String factoryType : container.getFactoryTypes(Page.PRODUCT_GROUP))
    {
      try
      {
        Page page = (Page)container.getElement(Page.PRODUCT_GROUP, factoryType, null);
        pages.add(page);
      }
      catch (Exception ex)
      {
        OM.LOG.error(ex);
      }
    }
  }

  /**
   * @since 4.1
   */
  protected IManagedContainer getPagesContainer()
  {
    return IPluginContainer.INSTANCE;
  }

  @Override
  protected void doActivate() throws Exception
  {
    initPages(pages);

    try
    {
      serverSocket = new ServerSocket(port);
    }
    catch (Exception ex)
    {
      throw new IllegalStateException("Could not open socket on port " + port, ex);
    }

    super.doActivate();
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    serverSocket.close();
    super.doDeactivate();
  }

  /**
   * A {@link CDOServerBrowser server browser} for the repositories in a {@link IManagedContainer managed container}.
   *
   * @author Eike Stepper
   */
  public static class ContainerBased extends CDOServerBrowser
  {
    private IContainer<?> container;

    private IListener containerListener = new ContainerEventAdapter<Object>()
    {
      @Override
      protected void onAdded(IContainer<Object> container, Object element)
      {
        addElement(element);
      }

      @Override
      protected void onRemoved(IContainer<Object> container, Object element)
      {
        removeElement(element);
      }
    };

    public ContainerBased(IContainer<?> container)
    {
      super(new HashMap<String, InternalRepository>());
      this.container = container;
    }

    public ContainerBased()
    {
      this(IPluginContainer.INSTANCE);
    }

    public IContainer<?> getContainer()
    {
      return container;
    }

    @Override
    protected IManagedContainer getPagesContainer()
    {
      if (container instanceof IManagedContainer)
      {
        return (IManagedContainer)container;
      }

      return IPluginContainer.INSTANCE;
    }

    @Override
    protected void doActivate() throws Exception
    {
      super.doActivate();
      for (Object element : container.getElements())
      {
        addElement(element);
      }

      container.addListener(containerListener);
    }

    @Override
    protected void doDeactivate() throws Exception
    {
      container.removeListener(containerListener);
      super.doDeactivate();
    }

    private void addElement(Object element)
    {
      if (element instanceof InternalRepository)
      {
        InternalRepository repository = (InternalRepository)element;
        getRepositories().put(repository.getName(), repository);
      }
    }

    private void removeElement(Object element)
    {
      if (element instanceof InternalRepository)
      {
        InternalRepository repository = (InternalRepository)element;
        getRepositories().remove(repository.getName());
      }
    }

    /**
     * Creates {@link CDOServerBrowser server browsers} for the repositories in a {@link IManagedContainer managed
     * container}.
     *
     * @author Eike Stepper
     */
    public static class Factory extends org.eclipse.net4j.util.factory.Factory
    {
      public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.browsers";

      public static final String TYPE = "default";

      private IContainer<?> container;

      public Factory()
      {
        this(IPluginContainer.INSTANCE);
      }

      public Factory(IContainer<?> container)
      {
        super(PRODUCT_GROUP, TYPE);
        this.container = container;
      }

      public CDOServerBrowser.ContainerBased create(String description) throws ProductCreationException
      {
        CDOServerBrowser.ContainerBased browser = new CDOServerBrowser.ContainerBased(container);

        try
        {
          int port = 0;

          if (!StringUtil.isEmpty(description))
          {
            int digits = 0;
            for (int i = 0; i < description.length(); i++)
            {
              if (Character.isDigit(description.charAt(i)))
              {
                ++digits;
              }
              else
              {
                break;
              }
            }

            if (digits != 0)
            {
              port = Integer.parseInt(description.substring(0, digits));
            }
          }

          if (port == 0)
          {
            port = IOUtil.getFreePort();
          }

          browser.setPort(port);
        }
        catch (Exception ex)
        {
          OM.LOG.warn(ex);
        }

        return browser;
      }
    }
  }

  /**
   * Represents pluggable content for a {@link CDOServerBrowser server browser}.
   *
   * @author Eike Stepper
   */
  public static interface Page
  {
    public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.browserPages";

    public String getName();

    public String getLabel();

    public boolean canDisplay(InternalRepository repository);

    public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out);
  }

  /**
   * An abstract base implementation of a {@link Page server browser page}.
   *
   * @author Eike Stepper
   */
  public static abstract class AbstractPage implements Page
  {
    private String name;

    private String label;

    public AbstractPage(String name, String label)
    {
      this.name = name;
      this.label = label;
    }

    public String getName()
    {
      return name;
    }

    public String getLabel()
    {
      return label;
    }
  }

  /**
   * A {@link Page server browser page} that renders the package registry contents of a repository.
   *
   * @author Eike Stepper
   */
  public static class PackagesPage extends AbstractPage
  {
    public static final String NAME = "packages";

    public PackagesPage()
    {
      super(NAME, "Packages and Classes");
    }

    public boolean canDisplay(InternalRepository repository)
    {
      return true;
    }

    public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out)
    {
      String param = browser.getParam("classifier");
      InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
      for (InternalCDOPackageUnit unit : packageRegistry.getPackageUnits())
      {
        param = showPackage(unit.getTopLevelPackageInfo(), packageRegistry, browser, param, out, "&nbsp;&nbsp;");
      }
    }

    protected String showPackage(InternalCDOPackageInfo info, InternalCDOPackageRegistry packageRegistry,
        CDOServerBrowser browser, String param, PrintStream out, String prefix)
    {
      EPackage ePackage = info.getEPackage();
      out.println("<h3>" + prefix + ePackage.getName() + "&nbsp;&nbsp;[" + ePackage.getNsURI() + "]</h3>");

      for (EClassifier classifier : ePackage.getEClassifiers())
      {
        String name = classifier.getName();
        if (param == null)
        {
          param = name;
        }

        String label = name.equals(param) ? name : browser.href(name, getName(), "classifier", name);
        out.print(prefix + "&nbsp;&nbsp;<b>" + label);

        if (classifier instanceof EEnum)
        {
          EEnum eenum = (EEnum)classifier;
          out.print("&nbsp;&nbsp;" + eenum.getELiterals());
        }
        else if (classifier instanceof EDataType)
        {
          EDataType eDataType = (EDataType)classifier;
          out.print("&nbsp;&nbsp;" + eDataType.getInstanceClassName());
        }

        out.println("</b><br>");
      }

      for (EPackage sub : ePackage.getESubpackages())
      {
        InternalCDOPackageInfo subInfo = packageRegistry.getPackageInfo(sub);
        param = showPackage(subInfo, packageRegistry, browser, param, out, prefix + "&nbsp;&nbsp;");
      }

      return param;
    }
  }

  /**
   * A {@link Page server browser page} that renders the locking manager contents of a repository.
   *
   * @author Eike Stepper
   * @since 4.2
   */
  public static class LocksPage extends AbstractPage
  {
    public static final String NAME = "locks";

    public LocksPage()
    {
      super(NAME, "Locks");
    }

    public boolean canDisplay(InternalRepository repository)
    {
      return true;
    }

    public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out)
    {
      InternalLockManager lockingManager = repository.getLockingManager();
      for (InternalSession session : repository.getSessionManager().getSessions())
      {
        boolean sessionRendered = false;
        for (InternalView view : session.getViews())
        {
          Map<CDOID, LockGrade> locks = lockingManager.getLocks(view);
          if (locks != null && !locks.isEmpty())
          {
            if (!sessionRendered)
            {
              int sessionID = session.getSessionID();
              String userID = session.getUserID();
              out.println("<h3>Session&nbsp;" + sessionID + "&nbsp;&nbsp;[" + userID + "]</h3>");
              out.println("<ul>");
              sessionRendered = true;
            }

            out.println("<li>" + view + "</li>");
            out.println("<ul>");

            for (Entry<CDOID, LockGrade> entry : locks.entrySet())
            {
              out.println("<li>" + entry.getKey() + " = " + entry.getValue() + "</li>");
            }

            out.println("</ul>");
          }

          if (sessionRendered)
          {
            out.println("</ul>");
          }
        }
      }
    }
  }

  /**
   * A {@link Page server browser page} that renders {@link CDORevision revisions}.
   *
   * @author Eike Stepper
   */
  public static abstract class RevisionsPage extends AbstractPage
  {
    public RevisionsPage(String name, String label)
    {
      super(name, label);
    }

    public void display(final CDOServerBrowser browser, InternalRepository repository, PrintStream out)
    {
      Map<CDOBranch, List<CDORevision>> allRevisions = getAllRevisions(repository);
      Map<CDOID, List<CDORevision>> ids = getAllIDs(allRevisions);

      out.print("<table border=\"0\">\r\n");
      out.print("<tr>\r\n");

      out.print("<td valign=\"top\">\r\n");
      out.print("<table border=\"1\" cellpadding=\"2\"><tr><td>\r\n");
      final String[] revision = { browser.getParam("revision") };
      new AllRevisionsDumper.Stream.Html(allRevisions, out)
      {
        private StringBuilder versionsBuilder;

        private CDORevision lastRevision;

        @Override
        protected void dumpEnd(List<CDOBranch> branches)
        {
          dumpLastRevision();
          super.dumpEnd(branches);
        }

        @Override
        protected void dumpBranch(CDOBranch branch)
        {
          dumpLastRevision();
          super.dumpBranch(branch);
        }

        @Override
        protected void dumpRevision(CDORevision rev)
        {
          CDOID id = rev.getID();
          if (lastRevision != null && !id.equals(lastRevision.getID()))
          {
            dumpLastRevision();
          }

          if (versionsBuilder == null)
          {
            versionsBuilder = new StringBuilder();
          }
          else
          {
            versionsBuilder.append(" ");
          }

          String key = CDORevisionUtil.formatRevisionKey(rev);
          if (revision[0] == null)
          {
            revision[0] = key;
          }

          String version = getVersionPrefix(rev) + rev.getVersion();
          if (key.equals(revision[0]))
          {
            versionsBuilder.append("<b>" + version + "</b>");
          }
          else
          {
            versionsBuilder.append(browser.href(version, getName(), "revision", key));
          }

          lastRevision = rev;
        }

        protected void dumpLastRevision()
        {
          if (versionsBuilder != null)
          {
            PrintStream out = out();

            out.println("<tr>");
            out.println("<td valign=\"top\">&nbsp;&nbsp;&nbsp;&nbsp;");
            out.println(getCDOIDLabel(lastRevision));
            out.println("&nbsp;&nbsp;&nbsp;&nbsp;</td>");

            out.println("<td>");
            out.println(versionsBuilder.toString());
            out.println("</td>");
            out.println("</tr>");

            lastRevision = null;
            versionsBuilder = null;
          }
        }
      }.dump();

      out.print("</td></tr></table></td>\r\n");
      out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");

      if (revision[0] != null)
      {
        out.print("<td valign=\"top\">\r\n");
        showRevision(out, browser, allRevisions, ids, revision[0], repository);
        out.print("</td>\r\n");
      }

      out.print("</tr>\r\n");
      out.print("</table>\r\n");
    }

    /**
     * @since 4.0
     */
    protected void showRevision(PrintStream pout, CDOServerBrowser browser,
        Map<CDOBranch, List<CDORevision>> allRevisions, Map<CDOID, List<CDORevision>> ids, String key,
        InternalRepository repository)
    {
      CDORevisionKey revisionKey = CDORevisionUtil.parseRevisionKey(key, repository.getBranchManager());
      for (CDORevision revision : allRevisions.get(revisionKey.getBranch()))
      {
        if (revision.getVersion() == revisionKey.getVersion() && revision.getID().equals(revisionKey.getID()))
        {
          showRevision(pout, browser, ids, (InternalCDORevision)revision);
          return;
        }
      }
    }

    /**
     * @since 4.0
     */
    protected void showRevision(PrintStream pout, CDOServerBrowser browser, Map<CDOID, List<CDORevision>> ids,
        InternalCDORevision revision)
    {
      String className = revision.getEClass().toString();
      className = className.substring(className.indexOf(' '));
      className = StringUtil.replace(className, new String[] { "(", ")", "," }, new String[] { "<br>", "", "<br>" });
      className = className.substring("<br>".length() + 1);

      String created = CDOCommonUtil.formatTimeStamp(revision.getTimeStamp());
      String commitInfo = browser.href(created, HistoryPage.NAME, "time", String.valueOf(revision.getTimeStamp()));

      pout.print("<table border=\"1\" cellpadding=\"2\">\r\n");
      showKeyValue(pout, true, "type", "<b>" + revision.getClass().getSimpleName() + "</b>");
      showKeyValue(pout, true, "class", className);
      showKeyValue(pout, true, "id", getRevisionValue(revision.getID(), browser, ids, revision));
      showKeyValue(pout, true, "branch", revision.getBranch().getName() + "[" + revision.getBranch().getID() + "]");
      showKeyValue(pout, true, "version", revision.getVersion());
      showKeyValue(pout, true, "created", commitInfo);
      showKeyValue(pout, true, "revised", CDOCommonUtil.formatTimeStamp(revision.getRevised()));
      if (revision instanceof SyntheticCDORevision)
      {
        if (revision instanceof PointerCDORevision)
        {
          PointerCDORevision pointer = (PointerCDORevision)revision;
          CDOBranchVersion target = pointer.getTarget();
          CDOBranch branch = target.getBranch();
          int version = target.getVersion();

          String label = getVersionLabel("v", version, branch);
          CDORevisionKey targetKey = CDORevisionUtil.createRevisionKey(pointer.getID(), branch, version);
          String value = CDORevisionUtil.formatRevisionKey(targetKey);
          showKeyValue(pout, true, "target", browser.href(label, getName(), "revision", value));
        }
      }
      else
      {
        showKeyValue(pout, true, "resource", getRevisionValue(revision.getResourceID(), browser, ids, revision));
        showKeyValue(pout, true, "container", getRevisionValue(revision.getContainerID(), browser, ids, revision));
        showKeyValue(pout, true, "feature", revision.getContainingFeatureID());

        for (EStructuralFeature feature : revision.getClassInfo().getAllPersistentFeatures())
        {
          Object value = revision.getValue(feature);
          showKeyValue(pout, false, feature.getName(), getRevisionValue(value, browser, ids, revision));
        }
      }

      pout.print("</table>\r\n");
    }

    /**
     * @since 4.0
     */
    protected Object getRevisionValue(Object value, CDOServerBrowser browser, Map<CDOID, List<CDORevision>> ids,
        InternalCDORevision context)
    {
      if (value instanceof CDOID)
      {
        List<CDORevision> revisions = ids.get(value);
        if (revisions != null)
        {
          StringBuilder builder = new StringBuilder();
          builder.append(getCDOIDLabel(revisions.get(0)));

          if (browser != null)
          {
            builder.append("&nbsp;&nbsp;");
            for (CDORevision revision : revisions)
            {
              String versionPrefix = getVersionPrefix(revision);
              int version = revision.getVersion();
              CDOBranch branch = revision.getBranch();
              String label = getVersionLabel(versionPrefix, version, branch);

              builder.append(" ");
              if (revision == context)
              {
                builder.append(label);
              }
              else
              {
                builder.append(browser.href(label, getName(), "revision", CDORevisionUtil.formatRevisionKey(revision)));
              }
            }
          }

          return builder.toString();
        }
      }

      if (value instanceof Collection)
      {
        StringBuilder builder = new StringBuilder();
        for (Object element : (Collection<?>)value)
        {
          builder.append(builder.length() == 0 ? "" : "<br>");
          builder.append(getRevisionValue(element, browser, ids, context));
        }

        return builder.toString();
      }

      return value;
    }

    private String getVersionLabel(String versionPrefix, int version, CDOBranch branch)
    {
      String label = versionPrefix + version;
      String branchName = branch.getName();
      if (!CDOBranch.MAIN_BRANCH_NAME.equals(branchName))
      {
        label += "[" + branchName + "]";
      }
      return label;
    }

    private String getVersionPrefix(CDORevision revision)
    {
      if (revision instanceof PointerCDORevision)
      {
        return "p";
      }

      if (revision instanceof DetachedCDORevision)
      {
        return "d";
      }

      return "v";
    }

    /**
     * @since 4.0
     */
    protected void showKeyValue(PrintStream pout, boolean bg, String key, Object value)
    {
      String color = bg ? "EEEEEE" : "FFFFFF";
      pout.print("<tr bgcolor=\"" + color + "\">\r\n");
      pout.print("<td valign=\"top\"><b>" + key + "</b></td>\r\n");
      pout.print("<td valign=\"top\">");
      pout.print(value);
      pout.print("</td>\r\n");
      pout.print("</tr>\r\n");
    }

    protected abstract Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository);

    private Map<CDOID, List<CDORevision>> getAllIDs(Map<CDOBranch, List<CDORevision>> allRevisions)
    {
      Map<CDOID, List<CDORevision>> ids = CDOIDUtil.createMap();
      for (List<CDORevision> list : allRevisions.values())
      {
        for (CDORevision revision : list)
        {
          CDOID id = revision.getID();
          List<CDORevision> revisions = ids.get(id);
          if (revisions == null)
          {
            revisions = new ArrayList<CDORevision>();
            ids.put(id, revisions);
          }

          revisions.add(revision);
        }
      }

      return ids;
    }

    protected String getCDOIDLabel(CDORevision revision)
    {
      String label = revision.toString();
      return label.substring(0, label.indexOf(':'));
    }

    /**
     * A {@link Page server browser page} that renders the {@link CDORevision revisions} in a revision cache.
     *
     * @author Eike Stepper
     */
    public static class FromCache extends RevisionsPage
    {
      public static final String NAME = "crevisions";

      public FromCache()
      {
        super(NAME, "Revisions From Cache");
      }

      public boolean canDisplay(InternalRepository repository)
      {
        return true;
      }

      @Override
      protected Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository)
      {
        return repository.getRevisionManager().getCache().getAllRevisions();
      }
    }

    /**
     * A {@link Page server browser page} that renders the {@link CDORevision revisions} in a {@link IStore store}.
     *
     * @author Eike Stepper
     */
    public static class FromStore extends RevisionsPage
    {
      public static final String NAME = "srevisions";

      public FromStore()
      {
        super(NAME, "Revisions From Store");
      }

      public boolean canDisplay(InternalRepository repository)
      {
        return repository.getStore() instanceof CDOAllRevisionsProvider;
      }

      @Override
      protected Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository)
      {
        return ((CDOAllRevisionsProvider)repository.getStore()).getAllRevisions();
      }
    }
  }

  /**
   * A {@link Page server browser page} that renders {@link CDOLobInfo large object infos}.
   *
   * @author Eike Stepper
   */
  public static class LobsPage extends AbstractPage
  {
    public static final String NAME = "lobs";

    public LobsPage()
    {
      super(NAME, "Large Objects");
    }

    public boolean canDisplay(InternalRepository repository)
    {
      return true;
    }

    public void display(final CDOServerBrowser browser, InternalRepository repository, final PrintStream out)
    {
      out.print("<table border=\"0\">\r\n");
      out.print("<tr>\r\n");
      out.print("<td valign=\"top\">\r\n");

      final String param = browser.getParam("id");
      final Object[] details = { null, null, null };

      try
      {
        repository.handleLobs(0, 0, new CDOLobHandler()
        {
          public OutputStream handleBlob(byte[] id, long size)
          {
            if (showLob(out, "Blob", id, size, browser, param))
            {
              ByteArrayOutputStream result = new ByteArrayOutputStream();
              details[0] = result;
              details[1] = param;
              details[2] = size;
              return result;
            }

            return null;
          }

          public Writer handleClob(byte[] id, long size)
          {
            if (showLob(out, "Clob", id, size, browser, param))
            {
              CharArrayWriter result = new CharArrayWriter();
              details[0] = result;
              details[1] = param;
              details[2] = size;
              return result;
            }

            return null;
          }
        });
      }
      catch (IOException ex)
      {
        throw WrappedException.wrap(ex);
      }

      out.print("</td>\r\n");

      if (details[0] != null)
      {
        out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");
        out.print("<td valign=\"top\">\r\n");
        if (details[0] instanceof ByteArrayOutputStream)
        {
          ByteArrayOutputStream baos = (ByteArrayOutputStream)details[0];
          String hex = HexUtil.bytesToHex(baos.toByteArray());

          out.println("<h3>Blob " + details[1] + " (" + details[2] + ")</h3>");
          out.println("<pre>\r\n");
          for (int i = 0; i < hex.length(); i++)
          {
            out.print(hex.charAt(i));
            if ((i + 1) % 32 == 0)
            {
              out.print("\r\n");
            }
            else if ((i + 1) % 16 == 0)
            {
              out.print("  ");
            }
            else if ((i + 1) % 2 == 0)
            {
              out.print(" ");
            }
          }

          out.println("</pre>\r\n");
        }
        else
        {
          CharArrayWriter caw = (CharArrayWriter)details[0];
          out.println("<h3>Clob " + details[1] + " (" + details[2] + ")</h3>");
          out.println("<pre>" + caw + "</pre>");
        }

        out.print("</td>\r\n");
      }

      out.print("</tr>\r\n");
      out.print("</table>\r\n");
    }

    protected boolean showLob(PrintStream out, String type, byte[] id, long size, CDOServerBrowser browser,
        String param)
    {
      String hex = HexUtil.bytesToHex(id);
      boolean selected = hex.equals(param);
      String label = selected ? hex : browser.href(hex, getName(), "id", hex);
      out.println(type + " " + label + " (" + size + ")");
      return selected;
    }
  }

  /**
   * A {@link Page server browser page} that renders {@link CDOCommitInfo commit infos}.
   *
   * @author Eike Stepper
   */
  public static class HistoryPage extends AbstractPage
  {
    public static final String NAME = "history";

    public HistoryPage()
    {
      super(NAME, "Commit Infos");
    }

    public boolean canDisplay(InternalRepository repository)
    {
      return true;
    }

    public void display(final CDOServerBrowser browser, InternalRepository repository, final PrintStream out)
    {
      out.print("<table border=\"0\">\r\n");
      out.print("<tr>\r\n");
      out.print("<td valign=\"top\">\r\n");

      IStoreAccessor accessor = repository.getStore().getReader(null);
      StoreThreadLocal.setAccessor(accessor);

      final String param = browser.getParam("time");

      out.print("<table border=\"1\" cellpadding=\"2\">\r\n");
      out.print("<tr>\r\n");
      out.print("<td valign=\"top\">Time</td>\r\n");
      out.print("<td valign=\"top\">Branch</td>\r\n");
      out.print("<td valign=\"top\">User</td>\r\n");
      out.print("<td valign=\"top\">Comment</td>\r\n");
      out.print("</tr>\r\n");

      final CDOCommitInfo[] details = { null };

      try
      {
        final boolean auditing = repository.isSupportingAudits();
        repository.getCommitInfoManager().getCommitInfos(null, 0L, 0L, new CDOCommitInfoHandler()
        {
          public void handleCommitInfo(CDOCommitInfo commitInfo)
          {
            if (showCommitInfo(out, commitInfo, browser, param, auditing))
            {
              details[0] = commitInfo;
            }
          }
        });

        out.print("</table>\r\n");
        out.print("</td>\r\n");
        out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");
        out.print("<td valign=\"top\">\r\n");

        if (auditing)
        {
          CDOCommitInfo commitInfo = details[0];
          if (commitInfo != null)
          {
            out.print("<h3>Commit Info " + commitInfo.getTimeStamp() + "</h3>\r\n");
            showCommitData(out, commitInfo, browser);
          }
        }
        else
        {
          out.print("<h3>No audit data available in this repository.</h3>\r\n");
        }

        out.print("</td>\r\n");
        out.print("</tr>\r\n");
        out.print("</table>\r\n");
      }
      finally
      {
        StoreThreadLocal.release();
      }
    }

    protected boolean showCommitInfo(PrintStream out, CDOCommitInfo commitInfo, CDOServerBrowser browser, String param,
        boolean auditing)
    {
      String timeStamp = String.valueOf(commitInfo.getTimeStamp());
      boolean selected = timeStamp.equals(param);

      String formatted = CDOCommonUtil.formatTimeStamp(commitInfo.getTimeStamp()).replaceAll(" ", "&nbsp;");
      String label = formatted;
      if (!selected && auditing)
      {
        label = browser.href(formatted, getName(), "time", timeStamp);
      }

      out.print("<tr>\r\n");
      out.print("<td valign=\"top\">\r\n");
      out.print(label);
      out.print("</td>\r\n");

      CDOBranch branch = commitInfo.getBranch();
      out.print("<td valign=\"top\">\r\n");
      out.print(branch.getName() + "[" + branch.getID() + "]");
      out.print("</td>\r\n");

      String userID = commitInfo.getUserID();
      out.print("<td valign=\"top\">\r\n");
      out.print(StringUtil.isEmpty(userID) ? "&nbsp;" : browser.escape(userID));
      out.print("</td>\r\n");

      String comment = commitInfo.getComment();
      out.print("<td valign=\"top\">\r\n");
      out.print(StringUtil.isEmpty(comment) ? "&nbsp;" : browser.escape(comment));
      out.print("</td>\r\n");

      out.print("</tr>\r\n");
      return selected;
    }

    protected void showCommitData(PrintStream out, CDOCommitInfo commitInfo, CDOServerBrowser browser)
    {
      out.print("<h4>New Objects:</h4>\r\n");
      out.print("<ul>\r\n");
      for (CDOIDAndVersion key : commitInfo.getNewObjects())
      {
        CDORevision newObject = (CDORevision)key;
        out.print("<li>" + browser.href(newObject.toString(), RevisionsPage.FromStore.NAME, "revision",
            CDORevisionUtil.formatRevisionKey(newObject)) + "<br>\r\n");
      }

      out.print("</ul>\r\n");
      out.print("<h4>Changed Objects:</h4>\r\n");
      out.print("<ul>\r\n");
      for (CDORevisionKey key : commitInfo.getChangedObjects())
      {
        CDORevisionDelta changedObject = (CDORevisionDelta)key;
        out.print("<li>" + changedObject.toString() + "<br>\r\n");
      }

      out.print("</ul>\r\n");
      out.print("<h4>Detached Objects:</h4>\r\n");
      out.print("<ul>\r\n");
      for (CDOIDAndVersion key : commitInfo.getDetachedObjects())
      {
        out.print("<li>" + key.toString() + "<br>\r\n");
      }

      out.print("</ul>\r\n");
    }
  }
}
