Merge "Ignoring vi swap file"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 527e4de..0b7eaeb 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1909,6 +1909,12 @@
 If the file doesn't exist or can't be read the default robots.txt file
 bundled with the .war will be used instead.
 
+[[httpd.registerMBeans]]httpd.registerMBeans::
++
+Enable (or disable) registration of Jetty MBeans for Java JMX.
++
+By default, false.
+
 [[index]]
 === Section index
 
diff --git a/Documentation/config-labels.txt b/Documentation/config-labels.txt
index fc25f22..0fe12ca 100644
--- a/Documentation/config-labels.txt
+++ b/Documentation/config-labels.txt
@@ -169,6 +169,20 @@
 optional leading `+`.
 
 
+[[label_defaultValue]]
+=== `label.Label-Name.defaultValue`
+
+The default value (or score) for the label.  The defaultValue must be
+within the range of valid label values.  It is an optional label setting,
+if not defined the defaultValue for the label will be 0.  When a
+defaultValue is defined, that value will get set in the Reply dialog
+by default.
+
+A defaultValue can be set to a score that is outside of the permissible
+range for a user.  In that case the score that will get set in the Reply
+box will be either the lowest or highest score in the permissible range.
+
+
 [[label_abbreviation]]
 === `label.Label-Name.abbreviation`
 
@@ -297,6 +311,32 @@
 copyright` will block submit, while `+1 Copyright clear` is required to
 enable submit.
 
+=== Default Value Example
+
+This example attempts to describe how a label default value works with the
+user permissions.  Assume the configuration below.
+
+====
+  [access "refs/heads/*"]
+      label-Snarky-Review = -3..+3 group Administrators
+      label-Snarky-Review = -2..+2 group Project Owners
+      label-Snarky-Review = -1..+1 group Registered Users
+  [label "Snarky-Review"]
+      value = -3 Ohh, hell no!
+      value = -2 Hmm, I'm not a fan
+      value = -1 I'm not sure I like this
+      value =  0 No score
+      value = +1 I like, but need another to like it as well
+      value = +2 Hmm, this is pretty nice
+      value = +3 Ohh, hell yes!
+      defaultValue = -3
+====
+
+Upon clicking the Reply button:
+* Administrators have all scores (-3..+3) available, -3 is set as the default.
+* Project Owners have limited scores (-2..+2) available, -2 is set as the default.
+* Registered Users have limited scores (-1..+1) available, -1 is set as the default.
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index 2fb256f..64fa9c4 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -171,6 +171,21 @@
 documentation for a full list of available access rights.
 
 
+[[mimetype-section]]
+=== MIME Types section
+
+The +mimetype+ section may be configured to force the web code
+reviewer to return certain MIME types by file path. MIME types
+may be used to activate syntax highlighting.
+
+----
+[mimetype "text/x-c"]
+  path = *.pkt
+[mimetype "text/x-java"]
+  path = api/current.txt
+----
+
+
 [[capability-section]]
 === Capability section
 
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 8f6b8a4..c172781 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -3093,6 +3093,8 @@
 |`value`       |optional|The voting value of the user who
 recommended/disliked this label on the change if it is not
 "`+1`"/"`-1`".
+|`default_value`|optional|The default voting value for the label.
+This value may be outside the range specified in permitted_labels.
 |===========================
 
 ==== Fields set by `DETAILED_LABELS`
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
index f3db988..7240036 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
@@ -69,6 +69,7 @@
     codeReview.setCopyMaxScore(false);
     codeReview.setCopyAllScoresOnTrivialRebase(false);
     codeReview.setCopyAllScoresIfNoCodeChange(false);
+    codeReview.setDefaultValue((short)-1);
     saveProjectConfig(cfg);
   }
 
@@ -264,6 +265,7 @@
     // through JSON instead of querying the DB directly.
     ChangeInfo c = get(r.getChangeId());
     LabelInfo cr = c.labels.get("Code-Review");
+    assertEquals(-1, (int) cr.defaultValue);
     assertEquals(1, cr.all.size());
     assertEquals("Administrator", cr.all.get(0).name);
     assertEquals(expected, cr.all.get(0).value.intValue());
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java
index d4f5b7b..28629b9 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java
@@ -27,10 +27,6 @@
 public class LabelType {
   public static LabelType withDefaultValues(String name) {
     checkName(name);
-    return withDefaultValuesDoNotCheckName(name);
-  }
-
-  public static LabelType withDefaultValuesDoNotCheckName(String name) {
     List<LabelValue> values = new ArrayList<>(2);
     values.add(new LabelValue((short) 0, "Rejected"));
     values.add(new LabelValue((short) 1, "Approved"));
@@ -112,6 +108,7 @@
   protected boolean copyMaxScore;
   protected boolean copyAllScoresOnTrivialRebase;
   protected boolean copyAllScoresIfNoCodeChange;
+  protected short defaultValue;
 
   protected List<LabelValue> values;
   protected short maxNegative;
@@ -129,6 +126,7 @@
     this.name = checkName(name);
     canOverride = true;
     values = sortValues(valueList);
+    defaultValue = 0;
 
     abbreviation = defaultAbbreviation(name);
     functionName = "MaxWithBlock";
@@ -204,6 +202,14 @@
     return v.getValue() > 0 ? v : null;
   }
 
+  public short getDefaultValue() {
+    return defaultValue;
+  }
+
+  public void setDefaultValue(short defaultValue) {
+    this.defaultValue = defaultValue;
+  }
+
   public boolean isCopyMinScore() {
     return copyMinScore;
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/LabelInfo.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/LabelInfo.java
index fd6008f..1e4edcd 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/LabelInfo.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/LabelInfo.java
@@ -25,6 +25,7 @@
   public List<ApprovalInfo> all;
   public Map<String, String> values;
   public Short value;
+  public Short defaultValue;
   public Boolean optional;
   public Boolean blocking;
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
index 2f646b7..f42bc75 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
@@ -139,8 +139,7 @@
   @UiField InlineHyperlink ownerLink;
   @UiField Element statusText;
   @UiField Image projectSettings;
-  @UiField Image projectDashboard;
-  @UiField InlineHyperlink projectLink;
+  @UiField InlineHyperlink projectDashboard;
   @UiField InlineHyperlink branchLink;
   @UiField Element strategy;
   @UiField Element submitActionText;
@@ -357,13 +356,6 @@
   }
 
   private void initProjectLinks(final ChangeInfo info) {
-    projectDashboard.addDomHandler(new ClickHandler() {
-      @Override
-      public void onClick(ClickEvent event) {
-        Gerrit.display(
-            PageLinks.toProjectDefaultDashboard(info.project_name_key()));
-      }
-    }, ClickEvent.getType());
     projectSettings.addDomHandler(new ClickHandler() {
       @Override
       public void onClick(ClickEvent event) {
@@ -371,12 +363,9 @@
             PageLinks.toProject(info.project_name_key()));
       }
     }, ClickEvent.getType());
-    projectLink.setText(info.project());
-    projectLink.setTargetHistoryToken(
-        PageLinks.toChangeQuery(
-            PageLinks.projectQuery(
-                info.project_name_key(),
-                info.status())));
+    projectDashboard.setText(info.project());
+    projectDashboard.setTargetHistoryToken(
+        PageLinks.toProjectDefaultDashboard(info.project_name_key()));
   }
 
   private void initBranchLink(ChangeInfo info) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
index 79bd162..f475ab1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
@@ -166,11 +166,6 @@
       cursor: pointer;
     }
 
-    .projectDashboard {
-      float: right;
-      cursor: pointer;
-    }
-
     .infoColumn {
       width: 440px;
       padding-left: 17px;
@@ -387,8 +382,8 @@
             </tr>
             <tr>
               <th><ui:msg>Project</ui:msg></th>
-              <td><x:InlineHyperlink ui:field='projectLink'
-                     title='Search for changes on this project'>
+              <td><x:InlineHyperlink ui:field='projectDashboard'
+                     title='Go to project dashboard'>
                      <ui:attribute name='title'/>
                   </x:InlineHyperlink>
                   <g:Image
@@ -398,13 +393,6 @@
                      title='Go to project settings'>
                     <ui:attribute name='title'/>
                   </g:Image>
-                  <g:Image
-                     ui:field='projectDashboard'
-                     resource='{ico.dashboard}'
-                     styleName='{style.projectDashboard}'
-                     title='Go to project dashboard'>
-                    <ui:attribute name='title'/>
-                  </g:Image>
               </td>
             </tr>
             <tr>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
index dc6d710..4e77041 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
@@ -322,10 +322,23 @@
     }
   }
 
+  private Short normalizeDefaultValue(Short defaultValue, Set<Short> permittedValues) {
+    Short pmin = Collections.min(permittedValues);
+    Short pmax = Collections.max(permittedValues);
+    Short dv = defaultValue;
+    if (dv > pmax) {
+      dv = pmax;
+    } else if (dv < pmin) {
+      dv = pmin;
+    }
+    return dv;
+  }
+
   private void renderRadio(int row,
       List<Short> columns,
       LabelAndValues lv) {
     String id = lv.info.name();
+    Short dv = normalizeDefaultValue(lv.info.defaultValue(), lv.permitted);
 
     labelHelpColumn = 1 + columns.size();
     labelsTable.setText(row, 0, id);
@@ -345,9 +358,10 @@
       if (lv.permitted.contains(v)) {
         String text = lv.info.value_text(LabelValue.formatValue(v));
         LabelRadioButton b = new LabelRadioButton(group, text, v);
-        if ((self != null && v == self.value()) || (self == null && v == 0)) {
+        if ((self != null && v == self.value()) || (self == null && v.equals(dv))) {
           b.setValue(true);
           group.select(b);
+          in.label(group.label, v);
           labelsTable.setText(row, labelHelpColumn, b.text);
         }
         group.buttons.add(b);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java
index b23403b..f2c97c1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java
@@ -84,7 +84,7 @@
     r.setCanRebase(can(rev.actions(), "rebase"));
     r.setCanRestore(can(info.actions(), "restore"));
     r.setCanRevert(can(info.actions(), "revert"));
-    r.setCanDeleteDraft(can(rev.actions(), "/"));
+    r.setCanDeleteDraft(can(info.actions(), "/"));
     r.setCanEditTopicName(can(info.actions(), "topic"));
     r.setCanSubmit(can(rev.actions(), "submit"));
     r.setCanEdit(true);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
index a627725..ed6f046 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
@@ -161,6 +161,7 @@
 
     public final native boolean optional() /*-{ return this.optional ? true : false; }-*/;
     public final native boolean blocking() /*-{ return this.blocking ? true : false; }-*/;
+    public final native short defaultValue() /*-{ return this.default_value; }-*/;
     final native short _value()
     /*-{
       if (this.value) return this.value;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java
index 840ebaa..320976e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CustomDashboardScreen.java
@@ -26,12 +26,7 @@
 
   @Override
   protected void onInitUI() {
-    table = new DashboardTable(params) {
-      @Override
-      protected void onLoad() {
-        super.onLoad();
-      }
-
+    table = new DashboardTable(this, params) {
       @Override
       public void finishDisplay() {
         super.finishDisplay();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java
index ac68722..978d4e5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DashboardTable.java
@@ -18,10 +18,13 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.Natives;
 import com.google.gerrit.client.ui.InlineHyperlink;
+import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.extensions.common.ListChangesOption;
 import com.google.gwt.core.client.JsArray;
+import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.http.client.URL;
+import com.google.gwtexpui.globalkey.client.KeyCommand;
 
 import java.util.ArrayList;
 import java.util.EnumSet;
@@ -34,7 +37,7 @@
   private List<String> titles;
   private List<String> queries;
 
-  public DashboardTable(String params) {
+  public DashboardTable(final Screen screen, String params) {
     titles = new ArrayList<>();
     queries = new ArrayList<>();
     String foreach = null;
@@ -72,6 +75,13 @@
       addSection(s);
       sections.add(s);
     }
+
+    keysNavigation.add(new KeyCommand(0, 'R', Util.C.keyReloadSearch()) {
+      @Override
+      public void onKeyPress(KeyPressEvent event) {
+        Gerrit.display(screen.getToken());
+      }
+    });
   }
 
   private String removeLimit(String query) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java
index 899e86b..d2eec27 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ProjectDashboardScreen.java
@@ -32,12 +32,7 @@
 
   @Override
   protected void onInitUI() {
-    table = new DashboardTable(params) {
-      @Override
-      protected void onLoad() {
-        super.onLoad();
-      }
-
+    table = new DashboardTable(this, params) {
       @Override
       public void finishDisplay() {
         super.finishDisplay();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
index ed7c3b6..0ef5272 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
@@ -32,6 +32,8 @@
 import com.google.gerrit.reviewdb.client.AccountDiffPreference.Theme;
 import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.RepeatingCommand;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.KeyDownEvent;
@@ -52,6 +54,12 @@
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.ToggleButton;
 
+import net.codemirror.lib.ModeInjector;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
 /** Displays current diff preferences. */
 class PreferencesBox extends Composite {
   interface Binder extends UiBinder<HTMLPanel, PreferencesBox> {}
@@ -83,6 +91,7 @@
   @UiField ToggleButton expandAllComments;
   @UiField ToggleButton renderEntireFile;
   @UiField ListBox theme;
+  @UiField ListBox mode;
   @UiField Button apply;
   @UiField Button save;
 
@@ -92,6 +101,7 @@
     initWidget(uiBinder.createAndBindUi(this));
     initIgnoreWhitespace();
     initTheme();
+    initMode();
   }
 
   @Override
@@ -114,6 +124,16 @@
         if (prefs.context() == WHOLE_FILE_CONTEXT) {
           contextEntireFile.setValue(true);
         }
+        if (view.canEnableRenderEntireFile(prefs)) {
+          renderEntireFile.setEnabled(true);
+        } else {
+          if (prefs.renderEntireFile()) {
+            prefs.renderEntireFile(false);
+            renderEntireFile.setValue(false);
+            view.updateRenderEntireFile();
+          }
+          renderEntireFile.setEnabled(false);
+        }
         view.setContext(prefs.context());
       }
     };
@@ -133,8 +153,14 @@
     manualReview.setValue(prefs.manualReview());
     expandAllComments.setValue(prefs.expandAllComments());
     renderEntireFile.setValue(prefs.renderEntireFile());
+    renderEntireFile.setEnabled(view.canEnableRenderEntireFile(prefs));
     setTheme(prefs.theme());
 
+    mode.setEnabled(prefs.syntaxHighlighting());
+    if (prefs.syntaxHighlighting()) {
+      setMode(view.getContentType());
+    }
+
     switch (view.getIntraLineStatus()) {
       case OFF:
       case OK:
@@ -277,9 +303,35 @@
   @UiHandler("syntaxHighlighting")
   void onSyntaxHighlighting(ValueChangeEvent<Boolean> e) {
     prefs.syntaxHighlighting(e.getValue());
+    mode.setEnabled(prefs.syntaxHighlighting());
+    if (prefs.syntaxHighlighting()) {
+      setMode(view.getContentType());
+    }
     view.setSyntaxHighlighting(prefs.syntaxHighlighting());
   }
 
+  @UiHandler("mode")
+  void onMode(ChangeEvent e) {
+    final String m = mode.getValue(mode.getSelectedIndex());
+    prefs.syntaxHighlighting(true);
+    syntaxHighlighting.setValue(true, false);
+    Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
+      @Override
+      public boolean execute() {
+        if (prefs.syntaxHighlighting() && view.isAttached()) {
+          view.operation(new Runnable() {
+            @Override
+            public void run() {
+              view.getCmFromSide(DisplaySide.A).setOption("mode", m);
+              view.getCmFromSide(DisplaySide.B).setOption("mode", m);
+            }
+          });
+        }
+        return false;
+      }
+    }, 50);
+  }
+
   @UiHandler("whitespaceErrors")
   void onWhitespaceErrors(ValueChangeEvent<Boolean> e) {
     prefs.showWhitespaceErrors(e.getValue());
@@ -374,6 +426,51 @@
         IGNORE_ALL_SPACE.name());
   }
 
+  private static final Map<String, String> NAME_TO_MODE;
+  private static final Map<String, String> NORMALIZED_MODES;
+  static {
+    NAME_TO_MODE = new TreeMap<String, String>();
+    NORMALIZED_MODES = new HashMap<String, String>();
+    for (String type : ModeInjector.getKnownMimeTypes()) {
+      String name = type;
+      if (name.startsWith("text/x-")) {
+        name = name.substring("text/x-".length());
+      } else if (name.startsWith("text/")) {
+        name = name.substring("text/".length());
+      } else if (name.startsWith("application/")) {
+        name = name.substring("application/".length());
+      }
+
+      String normalized = NAME_TO_MODE.get(name);
+      if (normalized == null) {
+        normalized = type;
+        NAME_TO_MODE.put(name, normalized);
+      }
+      NORMALIZED_MODES.put(type, normalized);
+    }
+  }
+
+  private void initMode() {
+    for (Map.Entry<String, String> e : NAME_TO_MODE.entrySet()) {
+      mode.addItem(e.getKey(), e.getValue());
+    }
+  }
+
+  private void setMode(String modeType) {
+    if (modeType != null && !modeType.isEmpty()) {
+      if (NORMALIZED_MODES.containsKey(modeType)) {
+        modeType =NORMALIZED_MODES.get(modeType);
+      }
+      for (int i = 0; i < mode.getItemCount(); i++) {
+        if (mode.getValue(i).equals(modeType)) {
+          mode.setSelectedIndex(i);
+          return;
+        }
+      }
+    }
+    mode.setSelectedIndex(0);
+  }
+
   private void setTheme(Theme v) {
     String name = v != null ? v.name() : Theme.DEFAULT.name();
     for (int i = 0; i < theme.getItemCount(); i++) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml
index d940590..b3ec067 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.ui.xml
@@ -204,6 +204,10 @@
         </g:ToggleButton></td>
       </tr>
       <tr>
+        <th><ui:msg>Language</ui:msg></th>
+        <td><g:ListBox ui:field='mode'/></td>
+      </tr>
+      <tr>
         <th><ui:msg>Whitespace Errors</ui:msg></th>
         <td><g:ToggleButton ui:field='whitespaceErrors'>
           <g:upFace><ui:msg>Hide</ui:msg></g:upFace>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
index ddf3978..db8c402 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.client.diff;
 
+import static com.google.gerrit.reviewdb.client.AccountDiffPreference.WHOLE_FILE_CONTEXT;
 import static java.lang.Double.POSITIVE_INFINITY;
 
 import com.google.gerrit.client.Gerrit;
@@ -24,6 +25,7 @@
 import com.google.gerrit.client.changes.ChangeInfo;
 import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
 import com.google.gerrit.client.changes.ChangeList;
+import com.google.gerrit.client.diff.DiffInfo.FileMeta;
 import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo;
 import com.google.gerrit.client.patches.PatchUtil;
 import com.google.gerrit.client.projects.ConfigInfoCache;
@@ -83,6 +85,18 @@
   interface Binder extends UiBinder<FlowPanel, SideBySide2> {}
   private static final Binder uiBinder = GWT.create(Binder.class);
 
+  enum FileSize {
+    SMALL(0),
+    LARGE(500),
+    HUGE(4000);
+
+    final int lines;
+
+    FileSize(int n) {
+      this.lines = n;
+    }
+  }
+
   @UiField(provided = true)
   Header header;
 
@@ -103,7 +117,7 @@
   private Element columnMarginB;
   private HandlerRegistration resizeHandler;
   private DiffInfo diff;
-  private boolean largeFile;
+  private FileSize fileSize;
   private ChunkManager chunkManager;
   private CommentManager commentManager;
   private SkipManager skipManager;
@@ -163,8 +177,8 @@
         public void onSuccess(DiffInfo diffInfo) {
           diff = diffInfo;
           if (prefs.syntaxHighlighting()) {
-            largeFile = isLargeFile(diffInfo);
-            if (largeFile) {
+            fileSize = bucketFileSize(diffInfo);
+            if (fileSize.compareTo(FileSize.SMALL) > 0) {
               modeInjectorCb.onSuccess(null);
             } else {
               injectMode(diffInfo, modeInjectorCb);
@@ -505,6 +519,11 @@
     cmA.getMoverElement().appendChild(columnMarginA);
     cmB.getMoverElement().appendChild(columnMarginB);
 
+    if (prefs.renderEntireFile() && !canEnableRenderEntireFile(prefs)) {
+      // CodeMirror is too slow to layout an entire huge file.
+      prefs.renderEntireFile(false);
+    }
+
     operation(new Runnable() {
       public void run() {
         // Estimate initial CM3 height, fixed up in onShowView.
@@ -526,7 +545,7 @@
     prefsAction = new PreferencesAction(this, prefs);
     header.init(prefsAction);
 
-    if (largeFile && prefs.syntaxHighlighting()) {
+    if (prefs.syntaxHighlighting() && fileSize.compareTo(FileSize.SMALL) > 0) {
       Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
         @Override
         public boolean execute() {
@@ -544,13 +563,16 @@
       String contents,
       DisplaySide side,
       Element parent) {
+    String mode = fileSize == FileSize.SMALL
+        ? getContentType(meta)
+        : null;
     return CodeMirror.create(side, parent, Configuration.create()
       .set("readOnly", true)
       .set("cursorBlinkRate", 0)
       .set("cursorHeight", 0.85)
       .set("lineNumbers", prefs.showLineNumbers())
       .set("tabSize", prefs.tabSize())
-      .set("mode", largeFile ? null : getContentType(meta))
+      .set("mode", mode)
       .set("lineWrapping", false)
       .set("styleSelectedText", true)
       .set("showTrailingSpace", prefs.showWhitespaceErrors())
@@ -564,6 +586,15 @@
     return diff.intraline_status();
   }
 
+  boolean canEnableRenderEntireFile(DiffPreferences prefs) {
+    return fileSize.compareTo(FileSize.HUGE) < 0
+        || (prefs.context() != WHOLE_FILE_CONTEXT && prefs.context() < 100);
+  }
+
+  String getContentType() {
+    return getContentType(diff.meta_b());
+  }
+
   void setThemeStyles(boolean d) {
     if (d) {
       diffTable.addStyleName(DiffTable.style.dark());
@@ -934,8 +965,17 @@
       });
   }
 
-  private static boolean isLargeFile(DiffInfo diffInfo) {
-    return (diffInfo.meta_a() != null && diffInfo.meta_a().lines() > 500)
-        || (diffInfo.meta_b() != null && diffInfo.meta_b().lines() > 500);
+  private static FileSize bucketFileSize(DiffInfo diff) {
+    FileMeta a = diff.meta_a();
+    FileMeta b = diff.meta_b();
+    FileSize[] sizes = FileSize.values();
+    for (int i = sizes.length - 1; 0 <= i; i--) {
+      FileSize s = sizes[i];
+      if ((a != null && s.lines <= a.lines())
+          || (b != null && s.lines <= b.lines())) {
+        return s;
+      }
+    }
+    return FileSize.SMALL;
   }
 }
diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/ModeInjector.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/ModeInjector.java
index 02faccb..3d77d09 100644
--- a/gerrit-gwtui/src/main/java/net/codemirror/lib/ModeInjector.java
+++ b/gerrit-gwtui/src/main/java/net/codemirror/lib/ModeInjector.java
@@ -21,6 +21,7 @@
 
 import net.codemirror.mode.Modes;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -94,6 +95,10 @@
     return real != null ? real : mode;
   }
 
+  public static Collection<String> getKnownMimeTypes() {
+    return mimeModes.keySet();
+  }
+
   private static native boolean isModeLoaded(String n)
   /*-{ return $wnd.CodeMirror.modes.hasOwnProperty(n); }-*/;
 
diff --git a/gerrit-pgm/BUCK b/gerrit-pgm/BUCK
index d1c468f..f76fa4c 100644
--- a/gerrit-pgm/BUCK
+++ b/gerrit-pgm/BUCK
@@ -115,6 +115,7 @@
     '//lib/guice:guice-servlet',
     '//lib/jetty:server',
     '//lib/jetty:servlet',
+    '//lib/jetty:jmx',
     '//lib/jgit:jgit',
     '//lib/log:api',
     '//lib/log:log4j',
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index 067eeab..60b5144 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -39,6 +39,7 @@
 import com.google.inject.servlet.GuiceServletContextListener;
 
 import org.eclipse.jetty.http.HttpScheme;
+import org.eclipse.jetty.jmx.MBeanContainer;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.ForwardedRequestCustomizer;
 import org.eclipse.jetty.server.Handler;
@@ -58,6 +59,7 @@
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -75,6 +77,7 @@
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.io.PrintWriter;
+import java.lang.management.ManagementFactory;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -171,6 +174,13 @@
       handler.setHandler(app);
       app = handler;
     }
+    if (cfg.getBoolean("httpd", "registerMBeans", false)) {
+      MBeanContainer mbean =
+          new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
+      httpd.addEventListener(mbean);
+      httpd.addBean(Log.getRootLogger());
+      httpd.addBean(mbean);
+    }
 
     httpd.setHandler(app);
     httpd.setStopAtShutdown(false);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
index 9d813fc..b82328c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
@@ -116,6 +116,7 @@
       lo.recommended = fromAcountInfo(li.recommended);
       lo.disliked = fromAcountInfo(li.disliked);
       lo.value = li.value;
+      lo.defaultValue = li.defaultValue;
       lo.optional = li.optional;
       lo.blocking = li.blocking;
       lo.values = li.values;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
index 5955fde..5321acd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
@@ -631,6 +631,7 @@
   }
 
   private void setLabelValues(LabelType type, LabelInfo label) {
+    label.defaultValue = type.getDefaultValue();
     label.values = Maps.newLinkedHashMap();
     for (LabelValue v : type.getValues()) {
       label.values.put(v.formatValue(), v.getText());
@@ -1007,6 +1008,7 @@
     public Map<String, String> values;
 
     public Short value;
+    public Short defaultValue;
     public Boolean optional;
     public Boolean blocking;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
index 7267f7d..3386e38 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
@@ -33,9 +33,11 @@
 import com.google.gerrit.reviewdb.client.AccountDiffPreference;
 import com.google.gerrit.reviewdb.client.Patch.ChangeType;
 import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.server.git.LargeObjectException;
 import com.google.gerrit.server.patch.PatchScriptFactory;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.git.LargeObjectException;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -55,6 +57,7 @@
 import java.util.concurrent.TimeUnit;
 
 public class GetDiff implements RestReadView<FileResource> {
+  private final ProjectCache projectCache;
   private final PatchScriptFactory.Factory patchScriptFactoryFactory;
   private final Provider<Revisions> revisions;
 
@@ -71,8 +74,10 @@
   boolean intraline;
 
   @Inject
-  GetDiff(PatchScriptFactory.Factory patchScriptFactoryFactory,
+  GetDiff(ProjectCache projectCache,
+      PatchScriptFactory.Factory patchScriptFactoryFactory,
       Provider<Revisions> revisions) {
+    this.projectCache = projectCache;
     this.patchScriptFactoryFactory = patchScriptFactoryFactory;
     this.revisions = revisions;
   }
@@ -127,18 +132,21 @@
       }
       content.addCommon(ps.getA().size());
 
+      ProjectState state =
+          projectCache.get(resource.getRevision().getChange().getProject());
+
       Result result = new Result();
       if (ps.getDisplayMethodA() != DisplayMethod.NONE) {
         result.metaA = new FileMeta();
         result.metaA.name = Objects.firstNonNull(ps.getOldName(), ps.getNewName());
-        result.metaA.setContentType(ps.getFileModeA(), ps.getMimeTypeA());
+        setContentType(result.metaA, state, ps.getFileModeA(), ps.getMimeTypeA());
         result.metaA.lines = ps.getA().size();
       }
 
       if (ps.getDisplayMethodB() != DisplayMethod.NONE) {
         result.metaB = new FileMeta();
         result.metaB.name = ps.getNewName();
-        result.metaB.setContentType(ps.getFileModeB(), ps.getMimeTypeB());
+        setContentType(result.metaB, state, ps.getFileModeB(), ps.getMimeTypeB());
         result.metaB.lines = ps.getB().size();
       }
 
@@ -182,21 +190,31 @@
     String name;
     String contentType;
     Integer lines;
+  }
 
-    void setContentType(FileMode fileMode, String mimeType) {
-      switch (fileMode) {
-        case FILE:
-          contentType = mimeType;
-          break;
-        case GITLINK:
-          contentType = "x-git/gitlink";
-          break;
-        case SYMLINK:
-          contentType = "x-git/symlink";
-          break;
-        default:
-          throw new IllegalStateException("file mode: " + fileMode);
-      }
+  private void setContentType(FileMeta meta, ProjectState project,
+      FileMode fileMode, String mimeType) {
+    switch (fileMode) {
+      case FILE:
+        if (project != null) {
+          for (ProjectState p : project.tree()) {
+            String t = p.getConfig().getMimeTypes().getMimeType(meta.name);
+            if (t != null) {
+              mimeType = t;
+              break;
+            }
+          }
+        }
+        meta.contentType = mimeType;
+        break;
+      case GITLINK:
+        meta.contentType = "x-git/gitlink";
+        break;
+      case SYMLINK:
+        meta.contentType = "x-git/symlink";
+        break;
+      default:
+        throw new IllegalStateException("file mode: " + fileMode);
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ConfiguredMimeTypes.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ConfiguredMimeTypes.java
new file mode 100644
index 0000000..082e1a2
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ConfiguredMimeTypes.java
@@ -0,0 +1,117 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import org.eclipse.jgit.errors.InvalidPatternException;
+import org.eclipse.jgit.fnmatch.FileNameMatcher;
+import org.eclipse.jgit.lib.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class ConfiguredMimeTypes {
+  private static final Logger log = LoggerFactory
+      .getLogger(ConfiguredMimeTypes.class);
+
+  private static final String MIMETYPE = "mimetype";
+  private static final String KEY_PATH = "path";
+
+  private final List<TypeMatcher> matchers;
+
+  ConfiguredMimeTypes(String projectName, Config rc) {
+    Set<String> types = rc.getSubsections(MIMETYPE);
+    if (types.isEmpty()) {
+      matchers = Collections.emptyList();
+    } else {
+      matchers = new ArrayList<>();
+      for (String typeName : types) {
+        for (String path : rc.getStringList(MIMETYPE, typeName, KEY_PATH)) {
+          try {
+            add(typeName, path);
+          } catch (PatternSyntaxException | InvalidPatternException e) {
+            log.warn(String.format(
+                "Ignoring invalid %s.%s.%s = %s in project %s: %s",
+                MIMETYPE, typeName, KEY_PATH,
+                path, projectName, e.getMessage()));
+          }
+        }
+      }
+    }
+  }
+
+  private void add(String typeName, String path)
+      throws PatternSyntaxException, InvalidPatternException {
+    if (path.startsWith("^")) {
+      matchers.add(new ReType(typeName, path));
+    } else {
+      matchers.add(new FnType(typeName, path));
+    }
+  }
+
+  public String getMimeType(String path) {
+    for (TypeMatcher m : matchers) {
+      if (m.matches(path)) {
+        return m.type;
+      }
+    }
+    return null;
+  }
+
+  private abstract static class TypeMatcher {
+    final String type;
+
+    TypeMatcher(String type) {
+      this.type = type;
+    }
+
+    abstract boolean matches(String path);
+  }
+
+  private static class FnType extends TypeMatcher {
+    private final FileNameMatcher matcher;
+
+    FnType(String type, String pattern) throws InvalidPatternException {
+      super(type);
+      this.matcher = new FileNameMatcher(pattern, null);
+    }
+
+    @Override
+    boolean matches(String input) {
+      FileNameMatcher m = new FileNameMatcher(matcher);
+      m.append(input);
+      return m.isMatch();
+    }
+  }
+
+  private static class ReType extends TypeMatcher {
+    private final Pattern re;
+
+    ReType(String type, String pattern) throws PatternSyntaxException {
+      super(type);
+      this.re = Pattern.compile(pattern);
+    }
+
+    @Override
+    boolean matches(String input) {
+      return re.matcher(input).matches();
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index 4971f84..5d4d946 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -43,9 +43,9 @@
 import com.google.gerrit.extensions.common.InheritableBoolean;
 import com.google.gerrit.extensions.common.SubmitType;
 import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.account.GroupBackend;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.PluginConfig;
@@ -129,6 +129,7 @@
   private static final String LABEL = "label";
   private static final String KEY_ABBREVIATION = "abbreviation";
   private static final String KEY_FUNCTION = "function";
+  private static final String KEY_DEFAULT_VALUE = "defaultValue";
   private static final String KEY_COPY_MIN_SCORE = "copyMinScore";
   private static final String KEY_COPY_MAX_SCORE = "copyMaxScore";
   private static final String KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = "copyAllScoresOnTrivialRebase";
@@ -154,6 +155,7 @@
   private Map<String, ContributorAgreement> contributorAgreements;
   private Map<String, NotifyConfig> notifySections;
   private Map<String, LabelType> labelSections;
+  private ConfiguredMimeTypes mimeTypes;
   private List<CommentLinkInfo> commentLinkSections;
   private List<ValidationError> validationErrors;
   private ObjectId rulesId;
@@ -300,6 +302,10 @@
     return commentLinkSections;
   }
 
+  public ConfiguredMimeTypes getMimeTypes() {
+    return mimeTypes;
+  }
+
   public GroupReference resolve(AccountGroup group) {
     return resolve(GroupReference.forGroup(group));
   }
@@ -417,6 +423,7 @@
     loadNotifySections(rc, groupsByName);
     loadLabelSections(rc);
     loadCommentLinkSections(rc);
+    mimeTypes = new ConfiguredMimeTypes(projectName.get(), rc);
     loadPluginSections(rc);
     loadReceiveSection(rc);
   }
@@ -665,6 +672,15 @@
             KEY_FUNCTION, name, Joiner.on(", ").join(LABEL_FUNCTIONS))));
         label.setFunctionName(null);
       }
+
+      short dv = (short) rc.getInt(LABEL, name, KEY_DEFAULT_VALUE, 0);
+      if (isInRange(dv, values)) {
+        label.setDefaultValue(dv);
+      } else {
+        error(new ValidationError(PROJECT_CONFIG, String.format(
+            "Invalid %s \"%s\" for label \"%s\"",
+            KEY_DEFAULT_VALUE, dv, name)));
+      }
       label.setCopyMinScore(
           rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, false));
       label.setCopyMaxScore(
@@ -680,6 +696,15 @@
     }
   }
 
+  private boolean isInRange(short value, List<LabelValue> labelValues) {
+    for (LabelValue lv : labelValues) {
+      if (lv.getValue() == value) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   private List<String> getStringListOrNull(Config rc, String section,
       String subSection, String name) {
     String[] ac = rc.getStringList(section, subSection, name);
@@ -1018,6 +1043,8 @@
       } else {
         rc.unset(LABEL, name, KEY_ABBREVIATION);
       }
+
+      rc.setInt(LABEL, name, KEY_DEFAULT_VALUE, label.getDefaultValue());
       if (label.isCopyMinScore()) {
         rc.setBoolean(LABEL, name, KEY_COPY_MIN_SCORE, true);
       } else {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
index 4540017..db9b29d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
@@ -63,13 +63,19 @@
       //
       return false;
     }
+
     ProjectState project = projectCache.get(c.getDest().getParentKey());
     if (project == null) {
       // The project has disappeared.
       //
       return false;
     }
+
     LabelType labelType = type(project.getLabelTypes(), label);
+    if (labelType == null) {
+      return false; // Label is not defined by this project.
+    }
+
     boolean hasVote = false;
     for (PatchSetApproval p : object.currentApprovals()) {
       if (labelType.matches(p)) {
@@ -103,8 +109,7 @@
         return lt;
       }
     }
-
-    return LabelType.withDefaultValuesDoNotCheckName(toFind);
+    return null;
   }
 
   private boolean match(Change change, int value, Account.Id approver,
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
index 1a9f74b..7b3ede2 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
@@ -21,9 +21,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.google.common.collect.Iterables;
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.common.data.ContributorAgreement;
 import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.common.data.LabelType;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -47,6 +49,7 @@
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.Map;
 
 public class ProjectConfigTest extends LocalDiskRepositoryTestCase {
   private final GroupReference developers = new GroupReference(
@@ -115,6 +118,60 @@
   }
 
   @Test
+  public void testReadConfigLabelDefaultValue() throws Exception {
+    RevCommit rev = util.commit(util.tree( //
+        util.file("groups", util.blob(group(developers))), //
+        util.file("project.config", util.blob(""//
+            + "[label \"CustomLabel\"]\n" //
+            + "  value = -1 Negative\n" //
+            + "  value =  0 No Score\n" //
+            + "  value =  1 Positive\n")) //
+        ));
+
+    ProjectConfig cfg = read(rev);
+    Map<String, LabelType> labels = cfg.getLabelSections();
+    Short dv = labels.entrySet().iterator().next().getValue().getDefaultValue();
+    assertEquals(0, (int) dv);
+  }
+
+  @Test
+  public void testReadConfigLabelDefaultValueInRange() throws Exception {
+    RevCommit rev = util.commit(util.tree( //
+        util.file("groups", util.blob(group(developers))), //
+        util.file("project.config", util.blob(""//
+            + "[label \"CustomLabel\"]\n" //
+            + "  value = -1 Negative\n" //
+            + "  value =  0 No Score\n" //
+            + "  value =  1 Positive\n" //
+            + "  defaultValue = -1\n")) //
+        ));
+
+    ProjectConfig cfg = read(rev);
+    Map<String, LabelType> labels = cfg.getLabelSections();
+    Short dv = labels.entrySet().iterator().next().getValue().getDefaultValue();
+    assertEquals(-1, (int) dv);
+  }
+
+  @Test
+  public void testReadConfigLabelDefaultValueNotInRange() throws Exception {
+    RevCommit rev = util.commit(util.tree( //
+        util.file("groups", util.blob(group(developers))), //
+        util.file("project.config", util.blob(""//
+            + "[label \"CustomLabel\"]\n" //
+            + "  value = -1 Negative\n" //
+            + "  value =  0 No Score\n" //
+            + "  value =  1 Positive\n" //
+            + "  defaultValue = -2\n")) //
+        ));
+
+    ProjectConfig cfg = read(rev);
+    assertEquals(1, cfg.getValidationErrors().size());
+    assertEquals("project.config: Invalid defaultValue \"-2\" "
+        + "for label \"CustomLabel\"",
+        Iterables.getOnlyElement(cfg.getValidationErrors()).getMessage());
+  }
+
+  @Test
   public void testEditConfig() throws Exception {
     RevCommit rev = util.commit(util.tree( //
         util.file("groups", util.blob(group(developers))), //
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
index 4756390..15a66ab 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
@@ -129,6 +129,7 @@
     assertNotNull(codeReview);
     assertEquals("Code-Review", codeReview.getName());
     assertEquals("CR", codeReview.getAbbreviation());
+    assertEquals(0, codeReview.getDefaultValue());
     assertEquals("MaxWithBlock", codeReview.getFunctionName());
     assertTrue(codeReview.isCopyMinScore());
     assertValueRange(codeReview, 2, 1, 0, -1, -2);
diff --git a/lib/jetty/BUCK b/lib/jetty/BUCK
index 9637598..a6fc4a7 100644
--- a/lib/jetty/BUCK
+++ b/lib/jetty/BUCK
@@ -60,6 +60,18 @@
 )
 
 maven_jar(
+  name = 'jmx',
+  id = 'org.eclipse.jetty:jetty-jmx:' + VERSION,
+  sha1 = 'eb1492a8c6362410f84c97907b2ffb94c4dfcc2f',
+  license = 'Apache2.0',
+  exported_deps = [
+    ':continuation',
+    ':http',
+  ],
+  exclude = EXCLUDE,
+)
+
+maven_jar(
   name = 'continuation',
   id = 'org.eclipse.jetty:jetty-continuation:' + VERSION,
   sha1 = '5751f7ea38488dd32180bd3273f7f8591928aee3',