[SPARK-1768] History server enhancements.

Two improvements to the history server:

- Separate the HTTP handling from history fetching, so that it's easy to add
  new backends later (thinking about SPARK-1537 in the long run)

- Avoid loading all UIs in memory. Do lazy loading instead, keeping a few in
  memory for faster access. This allows the app limit to go away, since holding
  just the listing in memory shouldn't be too expensive unless the user has millions
  of completed apps in the history (at which point I'd expect other issues to arise
  aside from history server memory usage, such as FileSystem.listStatus()
  starting to become ridiculously expensive).

I also fixed a few minor things along the way which aren't really worth mentioning.
I also removed the app's log path from the UI since that information may not even
exist depending on which backend is used (even though there is only one now).
I don't think there's a good solution here without a bigger change. The issue is that we want to list apps in some sensible order (current code uses end time), but when checking whether the app is up-to-date we need to compare its id. And just using a map doesn't allow us to have both.

So to avoid using more memory we'd have to reload every app from HDFS when rescanning, which can be pretty slow (and, with the check interval being 10s by default, pretty unfriendly to the NN).

At this point I'd like to defer a solution to this particular problem to a separate change. I've been playing with some ideas to solve this and other issues in the code, but that part is not yet ready for review.