several fixes to the doctor command
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index e2a65e7..a9ea8b2 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io';
+
+import '../base/os.dart';
 import '../doctor.dart';
 import '../globals.dart';
 import 'android_sdk.dart';
@@ -37,14 +40,47 @@
       if (androidSdk.latestVersion != null) {
         sdkVersionText = 'Android SDK ${androidSdk.latestVersion.buildToolsVersionName}';
 
-        messages.add(new ValidationMessage('Platform ${androidSdk.latestVersion.platformVersionName}'));
-        messages.add(new ValidationMessage('Build-tools ${androidSdk.latestVersion.buildToolsVersionName}'));
+        messages.add(new ValidationMessage(
+          'Platform ${androidSdk.latestVersion.platformVersionName}, '
+          'build-tools ${androidSdk.latestVersion.buildToolsVersionName}'
+        ));
       }
 
       List<String> validationResult = androidSdk.validateSdkWellFormed();
 
       if (validationResult.isEmpty) {
-        type = ValidationType.installed;
+        const String _kJdkDownload = 'https://www.oracle.com/technetwork/java/javase/downloads/';
+
+        String javaVersion;
+
+        try {
+          printTrace('java -version');
+
+          ProcessResult result = Process.runSync('java', <String>['-version']);
+          if (result.exitCode == 0) {
+            javaVersion = result.stderr;
+            List<String> versionLines = javaVersion.split('\n');
+            javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
+          }
+        } catch (error) {
+        }
+
+        if (javaVersion != null) {
+          type = ValidationType.installed;
+
+          messages.add(new ValidationMessage(javaVersion));
+
+          if (os.which('jarsigner') == null) {
+            messages.add(new ValidationMessage.error(
+              'The jarsigner utility was not found; this is used to build Android APKs. You may need to install\n'
+              'or re-install the Java JDK: $_kJdkDownload.'
+            ));
+          }
+        } else {
+          messages.add(new ValidationMessage.error(
+            'No Java SDK found; you can download Java from $_kJdkDownload.'
+          ));
+        }
       } else {
         messages.addAll(validationResult.map((String message) {
           return new ValidationMessage.error(message);
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index 4748b76..3d82ab5 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -189,12 +189,15 @@
 
     FlutterVersion version = FlutterVersion.getVersion();
 
-    messages.add(new ValidationMessage('Flutter root at ${version.flutterRoot}'));
-    messages.add(new ValidationMessage('Framework revision ${version.frameworkRevisionShort} '
-      '(${version.frameworkAge}, channel ${version.channel})'));
-    messages.add(new ValidationMessage('Engine revision ${version.engineRevisionShort}'));
+    messages.add(new ValidationMessage('Flutter at ${version.flutterRoot}'));
+    messages.add(new ValidationMessage(
+      'Framework revision ${version.frameworkRevisionShort} '
+      '(${version.frameworkAge}), '
+      'engine revision ${version.engineRevisionShort}'
+    ));
 
-    return new ValidationResult(ValidationType.installed, messages, statusInfo: osName());
+    return new ValidationResult(ValidationType.installed, messages,
+      statusInfo: 'on ${osName()}, channel ${version.channel}');
   }
 }
 
@@ -238,7 +241,7 @@
         File packageFile = new File(path.join(flutterPluginPath, 'package.json'));
         dynamic packageInfo = JSON.decode(packageFile.readAsStringSync());
         String version = packageInfo['version'];
-        messages.add(new ValidationMessage('Atom installed; flutter plugin version $version'));
+        messages.add(new ValidationMessage('Atom installed; Flutter plugin version $version'));
       } catch (error) {
         printTrace('Unable to read flutter plugin version: $error');
       }
diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
index 8df90c7..337026a 100644
--- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart
+++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 
+import '../base/os.dart';
 import '../base/process.dart';
 import '../doctor.dart';
 import 'mac.dart';
@@ -36,10 +37,11 @@
     if (xcode.isInstalled) {
       installCount++;
 
+      messages.add(new ValidationMessage('XCode at ${xcode.xcodeSelectPath}'));
+
       xcodeVersionInfo = xcode.xcodeVersionText;
       if (xcodeVersionInfo.contains(','))
         xcodeVersionInfo = xcodeVersionInfo.substring(0, xcodeVersionInfo.indexOf(','));
-
       messages.add(new ValidationMessage(xcode.xcodeVersionText));
 
       if (!xcode.isInstalledAndMeetsVersionCheck) {
@@ -62,18 +64,14 @@
     }
 
     // brew installed
-    if (exitsHappy(<String>['brew', '-v'])) {
+    if (os.which('brew') != null) {
       installCount++;
 
-      List<String> installed = <String>[];
-
       if (!exitsHappy(<String>['ideviceinstaller', '-h'])) {
         messages.add(new ValidationMessage.error(
           'ideviceinstaller not available; this is used to discover connected iOS devices.\n'
           'Install via \'brew install ideviceinstaller\'.'
         ));
-      } else {
-        installed.add('ideviceinstaller');
       }
 
       if (!hasIDeviceId) {
@@ -81,12 +79,7 @@
           'ios-deploy not available; this is used to deploy to connected iOS devices.\n'
           'Install via \'brew install ios-deploy\'.'
         ));
-      } else {
-        installed.add('ios-deploy');
       }
-
-      if (installed.isNotEmpty)
-          messages.add(new ValidationMessage(installed.join(', ') + ' installed'));
     } else {
       messages.add(new ValidationMessage.error(
         'Brew not installed; use this to install tools for iOS device development.\n'
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 388cc12..fd1db37 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -22,45 +22,49 @@
 const int kXcodeRequiredVersionMinor = 0;
 
 class XCode {
+  XCode() {
+    _eulaSigned = false;
+
+    try {
+      _xcodeSelectPath = runSync(<String>['xcode-select', '--print-path']);
+      _isInstalled = true;
+
+      _xcodeVersionText = runSync(<String>['xcodebuild', '-version']).replaceAll('\n', ', ');
+
+      try {
+        printTrace('xcrun clang');
+
+        ProcessResult result = Process.runSync('/usr/bin/xcrun', <String>['clang']);
+        if (result.stdout != null && result.stdout.contains('license'))
+          _eulaSigned = false;
+        else if (result.stderr != null && result.stderr.contains('license'))
+          _eulaSigned = false;
+        else
+          _eulaSigned = true;
+      } catch (error) {
+      }
+    } catch (error) {
+      _isInstalled = false;
+    }
+  }
+
   /// Returns [XCode] active in the current app context.
   static XCode get instance => context[XCode] ?? (context[XCode] = new XCode());
 
   bool get isInstalledAndMeetsVersionCheck => isInstalled && xcodeVersionSatisfactory;
 
+  String _xcodeSelectPath;
+  String get xcodeSelectPath => _xcodeSelectPath;
+
   bool _isInstalled;
-  bool get isInstalled {
-    if (_isInstalled != null) {
-      return _isInstalled;
-    }
+  bool get isInstalled => _isInstalled;
 
-    _isInstalled = exitsHappy(<String>['xcode-select', '--print-path']);
-    return _isInstalled;
-  }
-
+  bool _eulaSigned;
   /// Has the EULA been signed?
-  bool get eulaSigned {
-    if (!isInstalled)
-      return false;
-
-    try {
-      ProcessResult result = Process.runSync('/usr/bin/xcrun', <String>['clang']);
-      if (result.stdout != null && result.stdout.contains('license'))
-        return false;
-      if (result.stderr != null && result.stderr.contains('license'))
-        return false;
-      return true;
-    } catch (error) {
-      return false;
-    }
-  }
+  bool get eulaSigned => _eulaSigned;
 
   String _xcodeVersionText;
-
-  String get xcodeVersionText {
-    if (_xcodeVersionText == null)
-      _xcodeVersionText = runSync(<String>['xcodebuild', '-version']).replaceAll('\n', ', ');
-    return _xcodeVersionText;
-  }
+  String get xcodeVersionText => _xcodeVersionText;
 
   bool get xcodeVersionSatisfactory {
     RegExp regex = new RegExp(r'Xcode ([0-9.]+)');
diff --git a/packages/flutter_tools/lib/src/runner/version.dart b/packages/flutter_tools/lib/src/runner/version.dart
index e5dd189..eb0a53b 100644
--- a/packages/flutter_tools/lib/src/runner/version.dart
+++ b/packages/flutter_tools/lib/src/runner/version.dart
@@ -45,11 +45,10 @@
 
   @override
   String toString() {
-    String from = repositoryUrl == null ? 'Flutter from unknown source' : 'Flutter from $repositoryUrl (on channel $channel)';
-    String flutterText = 'Framework: $frameworkRevisionShort ($frameworkAge)';
-    String engineText =  'Engine:    $engineRevisionShort';
+    String from = 'Flutter on channel $channel (from ${repositoryUrl == null ? 'unknown source' : repositoryUrl})';
+    String flutterText = 'Framework revision $frameworkRevisionShort ($frameworkAge); engine revision $engineRevisionShort';
 
-    return '$from\n\n$flutterText\n$engineText';
+    return '$from\n$flutterText';
   }
 
   static FlutterVersion getVersion([String flutterRoot]) {