[SPARK-2321] [WIP] Stable pull-based progress / status API

This is a WIP pull request that proposes a stable, pull-based progress / status API for Spark (see [SPARK-2321](https://issues.apache.org/jira/browse/SPARK-2321)).  For now, I'd like to discuss the basic implementation, API names, and overall interface design.  Once we arrive at a good design, I'll go back and add additional methods to expose more information via these API.

#### Design goals:

- Pull-based API
- Usable from Java / Scala / Python
- Can be extended to expose more information without introducing binary incompatibilities.
- Returns immutable objects.
- Don't leak any implementation details, preserving our freedom to change the implementation.

#### Implementation:

- Add public methods (`getJobInfo`, `getStageInfo`) to SparkContext to allow status / progress information to be retrieved.
- Add public interfaces (`SparkJobInfo`, `SparkStageInfo`) for our API return values.  These interfaces consist entirely of Java-style getter methods.  The interfaces are currently implemented in Java.  I decided to explicitly separate the interface from its implementation (`SparkJobInfoImpl`, `SparkStageInfoImpl`) in order to prevent users from constructing these responses themselves.
- Move the construction of the web UI's SparkListeners into SparkContext and out of the web UI tabs themselves.  This allows us to re-use these listeners in the implementation of this status API.  There are a few reasons why this listener re-use makes sense:
   - The status API and web UI are guaranteed to show consistent information.
   - These listeners are already well-tested.
   - The same garbage-collection / information retention configurations can apply to both this API and the web UI.
- Extend JobProgressListener to maintain `jobId -> Job` and `stageId -> Stage` mappings.


#### Open questions:

- I'm open to naming suggestions / improvements.
- By implementing the interfaces in Java, we're limited in terms of how much Scala syntactic sugar we can provide for Scala users.  For example, paren-less accessor methods don't seem to work on Java interfaces, so this current API means that Scala users have to write

   ```scala
   sc.getJobInfo(0).stageIds()(0)
   ```
   
   to get the id of the first stage in a job.  On the other hand, this prevents us from introducing incompatibilities if we ever choose to overload the `getStages` method (or any other ones).

#### TODOs:

- [ ] Unit tests
- [ ] Examples
- [ ] Python API
- [ ] Documentation of new configuration options
The garbage collection / data retention semantics are the same as what's displayed in the Spark web UI, since we're built on top of the same listeners.  While a job is active, we'll keep information on it.  After the job completes / fails, a configurable maximum number of jobs and stages will be retained.  I'll be sure to clearly document this.

Regarding snapshots / consistency, I added a note about this in one of my commit messages, reproduced here:

```
- The "consistent snapshot of the entire job -> stage -> task mapping"
  semantics might be very expensive to implement for large jobs, so I've
  decided to remove chaining between SparkJobInfo and SparkStageInfo
  interfaces.  Concretely, this means that you can't write something like

     job.stages()(0).name

  to get the name of the first stage in a job.  Instead, you have to explicitly
  get the stage's ID from the job and then look up that stage using
  sc.getStageInfo().  This isn't to say that we can't implement methods like
  "getNumActiveStages" that reflect consistent state; the goal is mainly to
  avoid spending lots of time / memory to construct huge object graphs.
```

My concern was that it may be expensive to snapshot large jobs with many stages and tasks.