Rolling back "Add property provider generators" due to broken internal
builds.

Patch by: jat
Review by: unnurg (TBR)

Review at http://gwt-code-reviews.appspot.com/1063801


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9285 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/PropertyProviderGenerator.java b/dev/core/src/com/google/gwt/core/ext/linker/PropertyProviderGenerator.java
deleted file mode 100644
index fd8f1d3..0000000
--- a/dev/core/src/com/google/gwt/core/ext/linker/PropertyProviderGenerator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- * 
- * 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.gwt.core.ext.linker;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
-import java.util.SortedSet;
-
-/**
- * An interface for generating a property provider JS implementation, rather
- * than having it defined in a module file.
- * 
- * Use it like this:
- * <pre>
- *   &lt;property-provider name="foo" generator="org.example.FooGenerator"/&gt;
- * </pre>
- * A default implementation in JS can be included inside the property-provider
- * tag as usual, and will be used if the generator returns {@code null}.
- */
-public interface PropertyProviderGenerator {
-
-  /**
-   * Generate a property provider.
-   *
-   * @param logger TreeLogger
-   * @param possibleValues the possible values of this property
-   * @param fallback the fallback value for this property, or null
-   * @param configProperties the configuration properties for this module
-   * @return the JS source of the property provider (the complete body of a JS
-   *     function taking no arguments, including open/close braces), or null to
-   *     use the default implementation in the property-provider tag
-   * @throws UnableToCompleteException after logging the message if processing
-   *     is unable to continue
-   */
-  String generate(TreeLogger logger, SortedSet<String> possibleValues,
-      String fallback, SortedSet<ConfigurationProperty> configProperties)
-      throws UnableToCompleteException;
-}
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/SelectionProperty.java b/dev/core/src/com/google/gwt/core/ext/linker/SelectionProperty.java
index 6f27aba..8940edd 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/SelectionProperty.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/SelectionProperty.java
@@ -15,9 +15,6 @@
  */
 package com.google.gwt.core.ext.linker;
 
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-
 import java.util.SortedSet;
 
 /**
@@ -30,12 +27,6 @@
  *      used in generators.
  */
 public interface SelectionProperty {
-
-  /**
-   * Returns the fallback value or an empty string if not defined.
-   */
-  String getFallbackValue();
-
   /**
    * Returns the name of the deferred binding property.
    */
@@ -49,15 +40,8 @@
   /**
    * Returns a raw function body that provides the runtime value to be used for
    * a deferred binding property.
-   * 
-   * @param logger logger to use for any warnings/errors
-   * @param configProperties set of configuration properties
-   * @throws UnableToCompleteException if execution cannot continue, after
-   *     having logged a message
    */
-  String getPropertyProvider(TreeLogger logger,
-      SortedSet<ConfigurationProperty> configProperties)
-      throws UnableToCompleteException;
+  String getPropertyProvider();
 
   /**
    * Returns <code>true</code> if the value of the SelectionProperty is always
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/PermutationsUtil.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/PermutationsUtil.java
index c0367fa..f69cc48 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/PermutationsUtil.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/PermutationsUtil.java
@@ -18,7 +18,6 @@
 
 import com.google.gwt.core.ext.LinkerContext;
 import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.core.ext.linker.ArtifactSet;
 import com.google.gwt.core.ext.linker.SelectionProperty;
 import com.google.gwt.dev.util.StringKey;
@@ -73,16 +72,9 @@
   /**
    * Uses the internal map to insert JS to select a permutation into the
    * selection script.
-   * 
-   * @param selectionScript
-   * @param logger
-   * @param context
-   * @return the modified selectionScript buffer
-   * @throws UnableToCompleteException 
    */
   public StringBuffer addPermutationsJs(StringBuffer selectionScript,
-      TreeLogger logger, LinkerContext context)
-      throws UnableToCompleteException {
+      TreeLogger logger, LinkerContext context) {
     int startPos;
     
     PropertiesUtil.addPropertiesJs(selectionScript, logger, context);
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/PropertiesUtil.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/PropertiesUtil.java
index e645566..3ee5355 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/PropertiesUtil.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/PropertiesUtil.java
@@ -18,27 +18,21 @@
 
 import com.google.gwt.core.ext.LinkerContext;
 import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ConfigurationProperty;
 import com.google.gwt.core.ext.linker.SelectionProperty;
 
-import java.util.SortedSet;
-
 /**
  * A utility class to fill in the properties javascript in linker templates.
  */
 public class PropertiesUtil {
   public static StringBuffer addPropertiesJs(StringBuffer selectionScript,
-      TreeLogger logger, LinkerContext context)
-      throws UnableToCompleteException {
+      TreeLogger logger, LinkerContext context) {
     int startPos;
 
     // Add property providers
     startPos = selectionScript.indexOf("// __PROPERTIES_END__");
     if (startPos != -1) {
       for (SelectionProperty p : context.getProperties()) {
-        String text = generatePropertyProvider(logger, p,
-            context.getConfigurationProperties());
+        String text = generatePropertyProvider(p);
         selectionScript.insert(startPos, text);
         startPos += text.length();
       }
@@ -46,14 +40,12 @@
     return selectionScript;
   }
   
-  private static String generatePropertyProvider(TreeLogger logger,
-      SelectionProperty prop, SortedSet<ConfigurationProperty> configProps)
-      throws UnableToCompleteException {
+  private static String generatePropertyProvider(SelectionProperty prop) {
     StringBuffer toReturn = new StringBuffer();
 
     if (prop.tryGetValue() == null && !prop.isDerived()) {
       toReturn.append("providers['" + prop.getName() + "'] = function()");
-      toReturn.append(prop.getPropertyProvider(logger, configProps));
+      toReturn.append(prop.getPropertyProvider());
       toReturn.append(";");
 
       toReturn.append("values['" + prop.getName() + "'] = {");
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSelectionProperty.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSelectionProperty.java
index f50ae60..92b8670 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSelectionProperty.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSelectionProperty.java
@@ -15,10 +15,6 @@
  */
 package com.google.gwt.core.ext.linker.impl;
 
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ConfigurationProperty;
-import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
 import com.google.gwt.core.ext.linker.SelectionProperty;
 import com.google.gwt.dev.cfg.BindingProperty;
 
@@ -35,29 +31,22 @@
   private static final String FALLBACK_TOKEN = "/*-FALLBACK-*/";
 
   private final String activeValue;
-  private final String fallback;
   private final boolean isDerived;
   private final String name;
   private final String provider;
-  private final Class<? extends PropertyProviderGenerator> providerGenerator;
   private final SortedSet<String> values;
 
   public StandardSelectionProperty(BindingProperty p) {
     activeValue = p.getConstrainedValue();
     isDerived = p.isDerived();
     name = p.getName();
-    fallback = p.getFallback();
-    providerGenerator = p.getProviderGenerator();
+    String fallback = p.getFallback();
     provider = p.getProvider() == null ? null
         : p.getProvider().getBody().replace(FALLBACK_TOKEN, fallback);
     values = Collections.unmodifiableSortedSet(new TreeSet<String>(
         Arrays.asList(p.getDefinedValues())));
   }
 
-  public String getFallbackValue() {
-    return fallback;
-  }
-
   public String getName() {
     return name;
   }
@@ -66,27 +55,8 @@
     return values;
   }
 
-  public String getPropertyProvider(TreeLogger logger,
-      SortedSet<ConfigurationProperty> configProperties)
-      throws UnableToCompleteException {
-    String generatorResult = null;
-    if (providerGenerator != null) {
-      Throwable caught = null;
-      try {
-        PropertyProviderGenerator gen = providerGenerator.newInstance();
-        generatorResult = gen.generate(logger, values, fallback,
-            configProperties);
-      } catch (InstantiationException e) {
-        caught = e;
-      } catch (IllegalAccessException e) {
-        caught = e;
-      }
-      if (caught != null) {
-        logger.log(TreeLogger.WARN, "Failed to execute property provider "
-            + "generator '" + providerGenerator + "'", caught);
-      }
-    }
-    return generatorResult != null ? generatorResult : provider;
+  public String getPropertyProvider() {
+    return provider;
   }
 
   public boolean isDerived() {
diff --git a/dev/core/src/com/google/gwt/dev/cfg/BindingProperty.java b/dev/core/src/com/google/gwt/dev/cfg/BindingProperty.java
index 69e689c..5bea795 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/BindingProperty.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/BindingProperty.java
@@ -15,7 +15,6 @@
  */
 package com.google.gwt.dev.cfg;
 
-import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
 import com.google.gwt.dev.util.collect.IdentityHashSet;
 import com.google.gwt.dev.util.collect.Lists;
 import com.google.gwt.dev.util.collect.Sets;
@@ -49,7 +48,6 @@
   private final Map<Condition, SortedSet<String>> conditionalValues = new LinkedHashMap<Condition, SortedSet<String>>();
   private final SortedSet<String> definedValues = new TreeSet<String>();
   private PropertyProvider provider;
-  private Class<? extends PropertyProviderGenerator> providerGenerator;
   private String fallback;
   private final ConditionAll rootCondition = new ConditionAll();
 
@@ -136,11 +134,6 @@
     return definedValues.toArray(new String[definedValues.size()]);
   }
 
-  /**
-   * Returns the fallback value for this property, or the empty string if none.
-   * 
-   * @return the fallback value
-   */
   public String getFallback() {
     return fallback;
   }
@@ -149,13 +142,6 @@
     return provider;
   }
 
-  /**
-   * @return the the provider generator class, or null if none.
-   */
-  public Class<? extends PropertyProviderGenerator> getProviderGenerator() {
-    return providerGenerator;
-  }
-
   public Set<String> getRequiredProperties() {
     Set<String> toReturn = Sets.create();
     for (Condition cond : conditionalValues.keySet()) {
@@ -182,7 +168,8 @@
 
   /**
    * Returns <code>true</code> if the value was previously provided to
-   * {@link #addDefinedValue(Condition,String)}.
+   * {@link #addDefinedValue(String)} since the last time {@link #clearValues()}
+   * was called.
    */
   public boolean isDefinedValue(String value) {
     return definedValues.contains(value);
@@ -207,7 +194,7 @@
    * the currently-defined values.
    * 
    * @throws IllegalArgumentException if any of the provided values were not
-   *     provided to {@link #addDefinedValue(Condition,String)}.
+   *           provided to {@link #addDefinedValue(String)}.
    */
   public void setAllowedValues(Condition condition, String... values) {
     SortedSet<String> temp = new TreeSet<String>(Arrays.asList(values));
@@ -241,15 +228,6 @@
   }
 
   /**
-   * Set a provider generator for this property.
-   * 
-   * @param generator
-   */
-  public void setProviderGenerator(Class<? extends PropertyProviderGenerator> generator) {
-    providerGenerator = generator;
-  }
-
-  /**
    * Create a minimal number of equivalence sets, expanding any glob patterns.
    */
   void normalizeCollapsedValues() {
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
index d5653e7..fa76101 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
@@ -20,7 +20,6 @@
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.core.ext.linker.LinkerOrder;
-import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
 import com.google.gwt.dev.js.JsParser;
 import com.google.gwt.dev.js.JsParserException;
 import com.google.gwt.dev.js.ast.JsExprStmt;
@@ -50,151 +49,100 @@
 
   private final class BodySchema extends Schema {
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __add_linker_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __clear_configuration_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __collapse_all_properties_1_value = "true";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __collapse_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __collapse_property_2_values = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_configuration_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_configuration_property_2_is_multi_valued = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_linker_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_linker_2_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __define_property_2_values = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __entry_point_1_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __extend_configuration_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __extend_configuration_property_2_value = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __extend_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __extend_property_2_values = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __generate_with_1_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __inherits_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __property_provider_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
-    protected final String __property_provider_2_generator = "";
-
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_1_path = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_2_includes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_3_excludes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_4_skips = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_5_defaultexcludes = "yes";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __public_6_casesensitive = "true";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __replace_with_1_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __script_1_src = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __servlet_1_path = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __servlet_2_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_configuration_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_configuration_property_2_value = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_property_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_property_2_value = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_property_fallback_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __set_property_fallback_2_value = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_1_path = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_2_includes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_3_excludes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_4_skips = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_5_defaultexcludes = "yes";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __source_6_casesensitive = "true";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __stylesheet_1_src = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_1_path = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_2_includes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_3_excludes = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_4_skips = "";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_5_defaultexcludes = "yes";
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __super_source_6_casesensitive = "true";
 
     /**
@@ -205,7 +153,6 @@
 
     private Schema fChild;
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __add_linker_begin(LinkerName name)
         throws UnableToCompleteException {
       if (moduleDef.getLinker(name.name) == null) {
@@ -216,7 +163,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __clear_configuration_property_begin(PropertyName name)
         throws UnableToCompleteException {
       // Don't allow configuration properties with the same name as a
@@ -243,13 +189,11 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __collapse_all_properties_begin(boolean collapse) {
       moduleDef.setCollapseAllProperties(collapse);
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __collapse_property_begin(PropertyName name,
         PropertyValueGlob[] values) throws UnableToCompleteException {
       Property prop = moduleDef.getProperties().find(name.token);
@@ -291,7 +235,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __define_configuration_property_begin(PropertyName name,
         String is_multi_valued) throws UnableToCompleteException {
       boolean isMultiValued = toPrimitiveBoolean(is_multi_valued);
@@ -360,7 +303,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __define_linker_begin(LinkerName name,
         Class<? extends Linker> linker) throws UnableToCompleteException {
       if (!Linker.class.isAssignableFrom(linker)) {
@@ -377,7 +319,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __define_property_begin(PropertyName name,
         PropertyValue[] values) throws UnableToCompleteException {
 
@@ -410,13 +351,11 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __entry_point_begin(String className) {
       moduleDef.addEntryPointTypeName(className);
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __extend_configuration_property_begin(PropertyName name,
         String value) throws UnableToCompleteException {
 
@@ -439,7 +378,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __extend_property_begin(BindingProperty property,
         PropertyValue[] values) {
       for (int i = 0; i < values.length; i++) {
@@ -450,14 +388,12 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __fail_begin() {
       RuleFail rule = new RuleFail();
       moduleDef.getRules().prepend(rule);
       return new FullConditionSchema(rule.getRootCondition());
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __generate_with_begin(Class<? extends Generator> generator)
         throws UnableToCompleteException {
       if (!Generator.class.isAssignableFrom(generator)) {
@@ -470,7 +406,6 @@
       return new FullConditionSchema(rule.getRootCondition());
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __inherits_begin(String name)
         throws UnableToCompleteException {
       TreeLogger branch = logger.branch(TreeLogger.TRACE,
@@ -479,49 +414,36 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
-    protected Schema __property_provider_begin(BindingProperty property,
-        Class<? extends PropertyProviderGenerator> generator) {
-      fChild = new ScriptSchema();
-      return fChild;
+    @SuppressWarnings("unused")
+    protected Schema __property_provider_begin(BindingProperty property) {
+      return fChild = new ScriptSchema();
     }
 
-    @SuppressWarnings("unused") // called reflectively
-    protected void __property_provider_end(BindingProperty property,
-        Class<? extends PropertyProviderGenerator> generator)
+    protected void __property_provider_end(BindingProperty property)
         throws UnableToCompleteException {
-      if (generator != null
-          && !PropertyProviderGenerator.class.isAssignableFrom(generator)) {
-        logger.log(TreeLogger.ERROR, "A property provider generator must "
-            + "extend " + PropertyProviderGenerator.class.getName(), null);
-        throw new UnableToCompleteException();
-      }
       ScriptSchema childSchema = ((ScriptSchema) fChild);
       String script = childSchema.getScript();
-      property.setProviderGenerator(generator);
       if (script == null) {
-        if (generator == null) {
-          // This is a problem.
-          //
-          logger.log(TreeLogger.ERROR, "Property providers must specify a "
-              + "JavaScript body or a provider generator", null);
-          throw new UnableToCompleteException();
-        }
-      } else {
-        int lineNumber = childSchema.getStartLineNumber();
-        JsFunction fn = parseJsBlock(lineNumber, script);
-        property.setProvider(new PropertyProvider(fn.getBody().toSource()));
+        // This is a problem.
+        //
+        logger.log(TreeLogger.ERROR,
+            "Property providers must specify a JavaScript body", null);
+        throw new UnableToCompleteException();
       }
+
+      int lineNumber = childSchema.getStartLineNumber();
+      JsFunction fn = parseJsBlock(lineNumber, script);
+
+      property.setProvider(new PropertyProvider(fn.getBody().toSource()));
     }
 
-    @SuppressWarnings("unused") // called reflectively
+    @SuppressWarnings("unused")
     protected Schema __public_begin(String path, String includes,
         String excludes, String skips, String defaultExcludes,
         String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected void __public_end(String path, String includes, String excludes,
         String skips, String defaultExcludes, String caseSensitive) {
       IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
@@ -546,7 +468,6 @@
           skipList, doDefaultExcludes, doCaseSensitive);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __replace_with_begin(String className) {
       RuleReplaceWith rule = new RuleReplaceWith(className);
       moduleDef.getRules().prepend(rule);
@@ -557,12 +478,11 @@
      * @param src a partial or full url to a script file to inject
      * @return <code>null</code> since there can be no children
      */
-    @SuppressWarnings("unused") // called reflectively
+    @SuppressWarnings("unused")
     protected Schema __script_begin(String src) {
       return fChild = new ScriptSchema();
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected void __script_end(String src) {
       ScriptSchema childSchema = (ScriptSchema) fChild;
       String js = childSchema.getScript();
@@ -575,7 +495,6 @@
       moduleDef.getScripts().append(new Script(src));
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __servlet_begin(String path, String servletClass)
         throws UnableToCompleteException {
 
@@ -592,7 +511,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __set_configuration_property_begin(PropertyName name,
         String value) throws UnableToCompleteException {
 
@@ -629,14 +547,13 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
+    @SuppressWarnings("unused")
     protected Schema __set_property_begin(BindingProperty prop,
         PropertyValue[] value) throws UnableToCompleteException {
       bindingPropertyCondition = new ConditionAll();
       return new PropertyConditionSchema(bindingPropertyCondition);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected void __set_property_end(BindingProperty prop,
         PropertyValue[] value) throws UnableToCompleteException {
       boolean error = false;
@@ -660,7 +577,6 @@
       prop.setAllowedValues(bindingPropertyCondition, stringValues);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __set_property_fallback_begin(BindingProperty prop,
         PropertyValue value) throws UnableToCompleteException {
       boolean error = true;
@@ -684,14 +600,13 @@
      * Indicates which subdirectories contain translatable source without
      * necessarily adding a sourcepath entry.
      */
-    @SuppressWarnings("unused") // called reflectively
+    @SuppressWarnings("unused")
     protected Schema __source_begin(String path, String includes,
         String excludes, String skips, String defaultExcludes,
         String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected void __source_end(String path, String includes, String excludes,
         String skips, String defaultExcludes, String caseSensitive) {
       addSourcePackage(path, includes, excludes, skips, defaultExcludes,
@@ -702,7 +617,6 @@
      * @param src a partial or full url to a stylesheet file to inject
      * @return <code>null</code> since there can be no children
      */
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __stylesheet_begin(String src) {
       moduleDef.getStyles().append(src);
       return null;
@@ -712,14 +626,13 @@
      * Like adding a translatable source package, but such that it uses the
      * module's package itself as its sourcepath root entry.
      */
-    @SuppressWarnings("unused") // called reflectively
+    @SuppressWarnings("unused")
     protected Schema __super_source_begin(String path, String includes,
         String excludes, String skips, String defaultExcludes,
         String caseSensitive) {
       return fChild = new IncludeExcludeSchema();
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected void __super_source_end(String path, String includes,
         String excludes, String skips, String defaultExcludes,
         String caseSensitive) {
@@ -860,10 +773,6 @@
     @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
-      if (value.length() == 0) {
-        // handle optional class names
-        return null;
-      }
       try {
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         return cl.loadClass(value);
@@ -879,17 +788,14 @@
    */
   private final class FullConditionSchema extends PropertyConditionSchema {
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __when_type_assignable_1_class = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __when_type_is_1_class = null;
 
     public FullConditionSchema(CompoundCondition parentCondition) {
       super(parentCondition);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __when_type_assignable_begin(String className) {
       Condition cond = new ConditionWhenTypeAssignableTo(className);
       parentCondition.getConditions().add(cond);
@@ -898,7 +804,6 @@
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __when_type_is_begin(String className) {
       Condition cond = new ConditionWhenTypeIs(className);
       parentCondition.getConditions().add(cond);
@@ -915,13 +820,10 @@
 
   private static final class IncludeExcludeSchema extends Schema {
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __exclude_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __include_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __skip_1_name = null;
 
     /**
@@ -951,24 +853,21 @@
       return skips;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __exclude_begin(String name) {
       excludes.add(name);
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __include_begin(String name) {
       includes.add(name);
       return null;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __skip_begin(String name) {
       skips.add(name);
       return null;
     }
-  }
+}
 
   private static class LinkerName {
     public final String name;
@@ -983,7 +882,6 @@
    */
   private final class LinkerNameAttrCvt extends AttributeConverter {
 
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       // Ensure the value is a valid Java identifier
@@ -1014,7 +912,6 @@
    */
   private final class NullableNameAttrCvt extends AttributeConverter {
 
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       if (value == null || value.length() == 0) {
@@ -1048,7 +945,6 @@
       this.concreteType = concreteType;
     }
 
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       // Find the named property.
@@ -1078,13 +974,10 @@
    * A limited number of conditional predicates based only on properties.
    */
   private class PropertyConditionSchema extends Schema {
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __when_linker_added_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __when_property_is_1_name = null;
 
-    @SuppressWarnings("unused") // referenced reflectively
     protected final String __when_property_is_2_value = null;
 
     protected final CompoundCondition parentCondition;
@@ -1093,28 +986,24 @@
       this.parentCondition = parentCondition;
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __all_begin() {
       CompoundCondition cond = new ConditionAll();
       parentCondition.getConditions().add(cond);
       return subSchema(cond);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __any_begin() {
       CompoundCondition cond = new ConditionAny();
       parentCondition.getConditions().add(cond);
       return subSchema(cond);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __none_begin() {
       CompoundCondition cond = new ConditionNone();
       parentCondition.getConditions().add(cond);
       return subSchema(cond);
     }
 
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __when_linker_added_begin(LinkerName linkerName) {
       Condition cond = new ConditionWhenLinkerAdded(linkerName.name);
       parentCondition.getConditions().add(cond);
@@ -1128,7 +1017,6 @@
      * module writers. It prevents them from trying to create property providers
      * for unknown properties.
      */
-    @SuppressWarnings("unused") // called reflectively
     protected Schema __when_property_is_begin(BindingProperty prop,
         PropertyValue value) {
       Condition cond = new ConditionWhenPropertyIs(prop.getName(), value.token);
@@ -1156,7 +1044,6 @@
    */
   private final class PropertyNameAttrCvt extends AttributeConverter {
 
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       // Ensure each part of the name is valid.
@@ -1188,7 +1075,6 @@
    * Converts a comma-separated string into an array of property value tokens.
    */
   private final class PropertyValueArrayAttrCvt extends AttributeConverter {
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       String[] tokens = value.split(",");
@@ -1209,7 +1095,6 @@
    * Converts a string into a property value, validating it in the process.
    */
   private final class PropertyValueAttrCvt extends AttributeConverter {
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
 
@@ -1239,7 +1124,6 @@
    * Converts a comma-separated string into an array of property value tokens.
    */
   private final class PropertyValueGlobArrayAttrCvt extends AttributeConverter {
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
       String[] tokens = value.split(",");
@@ -1260,7 +1144,6 @@
    * Converts a string into a property value glob, validating it in the process.
    */
   private final class PropertyValueGlobAttrCvt extends AttributeConverter {
-    @Override
     public Object convertToArg(Schema schema, int line, String elem,
         String attr, String value) throws UnableToCompleteException {
 
@@ -1286,7 +1169,6 @@
     public ScriptSchema() {
     }
 
-    @SuppressWarnings("unused") // called reflectively
     public void __text(String text) {
       if (script == null) {
         script = new StringBuffer();
diff --git a/dev/core/test/com/google/gwt/core/ext/linker/impl/StandardSelectionPropertyTest.java b/dev/core/test/com/google/gwt/core/ext/linker/impl/StandardSelectionPropertyTest.java
index 1c646fa..19a4cb9 100644
--- a/dev/core/test/com/google/gwt/core/ext/linker/impl/StandardSelectionPropertyTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/linker/impl/StandardSelectionPropertyTest.java
@@ -15,37 +15,16 @@
  */
 package com.google.gwt.core.ext.linker.impl;
 
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ConfigurationProperty;
-import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
 import com.google.gwt.dev.cfg.BindingProperty;
 import com.google.gwt.dev.cfg.PropertyProvider;
-import com.google.gwt.dev.shell.FailErrorLogger;
 
 import junit.framework.TestCase;
 
-import java.util.SortedSet;
-import java.util.TreeSet;
-
 /**
  * Tests for {@link StandardSelectionProperty}.
  */
 public class StandardSelectionPropertyTest extends TestCase {
 
-  /**
-   * Test property provider generator.
-   */
-  public static class MyProviderGenerator
-      implements PropertyProviderGenerator {
-
-    public String generate(TreeLogger logger, SortedSet<String> possibleValues,
-        String fallback, SortedSet<ConfigurationProperty> configProperties)
-        throws UnableToCompleteException {
-      return "good " + fallback;
-    }
-  }
-
   private static final String FBV = "FBV";
 
   private static final String PROVIDER_MULTIFALLBACK =
@@ -57,49 +36,30 @@
 
   private static final String PROVIDER_NOFALLBACK = "provider text without fallback";
 
-  private static final TreeLogger logger = new FailErrorLogger();
-
-  private static final SortedSet<ConfigurationProperty> configProperties = new TreeSet<ConfigurationProperty>();
-
-  public void testNoFallback() throws UnableToCompleteException {
+  public void testNoFallback() {
     BindingProperty bp = new BindingProperty("doesNotUseFallback");
     PropertyProvider provider = new PropertyProvider(PROVIDER_NOFALLBACK);
     bp.setProvider(provider);
     StandardSelectionProperty property = new StandardSelectionProperty(bp);
-    assertEquals(PROVIDER_NOFALLBACK, property.getPropertyProvider(logger,
-        configProperties));
+    assertEquals(PROVIDER_NOFALLBACK, property.getPropertyProvider());
 
     provider = new PropertyProvider(PROVIDER_MULTIFALLBACK);
     bp.setProvider(provider);
     property = new StandardSelectionProperty(bp);
-    assertEquals(PROVIDER_MULTIFALLBACK_EMPTY, property.getPropertyProvider(
-        logger, configProperties));
+    assertEquals(PROVIDER_MULTIFALLBACK_EMPTY, property.getPropertyProvider());
   }
 
-  public void testPropertyProviderGenerator() throws UnableToCompleteException {
-    BindingProperty bp = new BindingProperty("providerGenerator");
-    bp.setFallback(FBV);
-    PropertyProvider provider = new PropertyProvider("bad");
-    bp.setProvider(provider);
-    bp.setProviderGenerator(MyProviderGenerator.class);
-    StandardSelectionProperty property = new StandardSelectionProperty(bp);
-    assertEquals("good " + FBV, property.getPropertyProvider(logger,
-        configProperties));
-  }
-
-  public void testWithFallback() throws UnableToCompleteException {
+  public void testWithFallback() {
     BindingProperty bp = new BindingProperty("doesUseFallback");
     bp.setFallback(FBV);
     PropertyProvider provider = new PropertyProvider(PROVIDER_NOFALLBACK);
     bp.setProvider(provider);
     StandardSelectionProperty property = new StandardSelectionProperty(bp);
-    assertEquals(PROVIDER_NOFALLBACK, property.getPropertyProvider(logger,
-        configProperties));
+    assertEquals(PROVIDER_NOFALLBACK, property.getPropertyProvider());
 
     provider = new PropertyProvider(PROVIDER_MULTIFALLBACK);
     bp.setProvider(provider);
     property = new StandardSelectionProperty(bp);
-    assertEquals(PROVIDER_MULTIFALLBACK_FBV, property.getPropertyProvider(
-        logger, configProperties));
+    assertEquals(PROVIDER_MULTIFALLBACK_FBV, property.getPropertyProvider());
   }
 }
diff --git a/distro-source/core/src/gwt-module.dtd b/distro-source/core/src/gwt-module.dtd
index 10c6614..fd59093 100644
--- a/distro-source/core/src/gwt-module.dtd
+++ b/distro-source/core/src/gwt-module.dtd
@@ -32,28 +32,28 @@
 <!ELEMENT source (include | exclude)*>
 <!ATTLIST source
 	path CDATA #REQUIRED
-	includes CDATA #IMPLIED
-	excludes CDATA #IMPLIED
-	defaultexcludes (yes | no) "yes"
-	casesensitive (true | false) "true"
+		includes CDATA #IMPLIED
+		excludes CDATA #IMPLIED
+		defaultexcludes (yes | no) "yes"
+		casesensitive (true | false) "true"
 >
 <!-- Specify the public resource path, relative to the classpath location of the module descriptor -->
 <!ELEMENT public (include | exclude)*>
 <!ATTLIST public
 	path CDATA #REQUIRED
-	includes CDATA #IMPLIED
-	excludes CDATA #IMPLIED
-	defaultexcludes (yes | no) "yes"
-	casesensitive (true | false) "true"
+		includes CDATA #IMPLIED
+		excludes CDATA #IMPLIED
+		defaultexcludes (yes | no) "yes"
+		casesensitive (true | false) "true"
 >
 <!-- Specify a source path that rebases subpackages into the root namespace -->
 <!ELEMENT super-source (include | exclude)*>
 <!ATTLIST super-source
 	path CDATA #REQUIRED
-	includes CDATA #IMPLIED
-	excludes CDATA #IMPLIED
-	defaultexcludes (yes | no) "yes"
-	casesensitive (true | false) "true"
+		includes CDATA #IMPLIED
+		excludes CDATA #IMPLIED
+		defaultexcludes (yes | no) "yes"
+		casesensitive (true | false) "true"
 >
 <!ELEMENT include EMPTY>
 <!ATTLIST include
@@ -160,7 +160,6 @@
 <!ELEMENT property-provider (#PCDATA)>
 <!ATTLIST property-provider
 	name CDATA #REQUIRED
-	generator CDATA #IMPLIED
 >
 <!-- All possible predicates -->
 <!ENTITY % predicates "when-property-is | when-type-assignable | when-type-is | all | any | none">
diff --git a/tools/api-checker/config/gwt20_21userApi.conf b/tools/api-checker/config/gwt20_21userApi.conf
index 216ac23..b79ca67 100644
--- a/tools/api-checker/config/gwt20_21userApi.conf
+++ b/tools/api-checker/config/gwt20_21userApi.conf
@@ -10,6 +10,7 @@
 :com/google/gwt/benchmarks/BenchmarkShell.java\
 :com/google/gwt/benchmarks/client/Benchmark.java\
 :com/google/gwt/core/ext/**\
+:com/google/gwt/core/linker/**\
 :com/google/gwt/dev/*.java\
 :com/google/gwt/dev/asm/**\
 :com/google/gwt/dev/cfg/**\
@@ -27,9 +28,9 @@
 :com/google/gwt/resources/css/**\
 :com/google/gwt/resources/ext/**\
 :com/google/gwt/resources/rg/**\
+:com/google/gwt/user/linker/**\
 :com/google/gwt/util/**\
 :com/google/gwt/soyc/**\
-:**/linker/**\
 :**/rebind/**\
 :**/remote/**\
 :**/server/**\
@@ -41,6 +42,7 @@
 :com/google/gwt/regexp/shared/**\
 :com/google/gwt/rpc/client/impl/ClientWriterFactory.java\
 :com/google/gwt/rpc/client/impl/EscapeUtil.java\
+:com/google/gwt/rpc/linker/*.java\
 :com/google/gwt/uibinder/attributeparsers/*.java\
 :com/google/gwt/uibinder/elementparsers/*.java\
 :com/google/gwt/uibinder/testing/*.java\
@@ -62,7 +64,6 @@
 excludedFiles_new user/src/com/google/gwt/benchmarks/BenchmarkReport.java\
 :user/src/com/google/gwt/benchmarks/BenchmarkShell.java\
 :user/src/com/google/gwt/benchmarks/client/Benchmark.java\
-:**/linker/**\
 :**/rebind/**\
 :**/server/**\
 :**/tools/**\
@@ -73,14 +74,17 @@
 :user/src/com/google/gwt/junit/client/GWTTestCase.java\
 :user/src/com/google/gwt/junit/client/impl/GWTRunner.java\
 :user/src/com/google/gwt/junit/remote\
+:user/src/com/google/gwt/precompress/linker\
 :user/src/com/google/gwt/resources/css\
 :user/src/com/google/gwt/resources/ext\
 :user/src/com/google/gwt/resources/rg\
 :user/src/com/google/gwt/requestfactory/shared/impl/MessageFactoryHolder.java\
 :user/src/com/google/gwt/rpc/client/impl/ClientWriterFactory.java\
 :user/src/com/google/gwt/rpc/client/impl/EscapeUtil.java\
+:user/src/com/google/gwt/rpc/linker\
 :user/src/com/google/gwt/safehtml/shared/SafeHtmlHostedModeUtils.java\
 :user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java\
+:user/src/com/google/gwt/user/linker\
 :user/src/com/google/gwt/uibinder/attributeparsers\
 :user/src/com/google/gwt/uibinder/elementparsers\
 :user/src/com/google/gwt/uibinder/testing\
diff --git a/user/src/com/google/gwt/i18n/I18N.gwt.xml b/user/src/com/google/gwt/i18n/I18N.gwt.xml
index a22c58f..00d90ca 100644
--- a/user/src/com/google/gwt/i18n/I18N.gwt.xml
+++ b/user/src/com/google/gwt/i18n/I18N.gwt.xml
@@ -23,56 +23,60 @@
   <!-- 'default' is always defined.                                    -->
   <define-property name="locale" values="default" />
 
-  <!--
-   - Configuration property defining the query parameter to use for the locale.
-   - Valid values are any legal URL query parameter name. 
-   -->
-  <define-configuration-property name="locale.queryparam"
-      is-multi-valued="false"/>
-  <set-configuration-property name="locale.queryparam" value="locale"/>
+  <property-provider name="locale">
+    <![CDATA[
+      try {
+      var locale;
+      var defaultLocale = "/*-FALLBACK-*/" || 'default';
 
-  <!--
-   - Configuration property defining the cookie to use for the locale.
-   - Valid values are any legal cookie name. 
-   -->
-  <define-configuration-property name="locale.cookie" is-multi-valued="false"/>
-  <set-configuration-property name="locale.cookie" value=""/>
+      // Look for the locale as a url argument
+      if (locale == null) {
+        var args = location.search;
+        var startLang = args.indexOf("locale=");
+        if (startLang >= 0) {
+          var language = args.substring(startLang);
+          var begin = language.indexOf("=") + 1;
+          var end = language.indexOf("&");
+          if (end == -1) {
+            end = language.length;
+          }
+          locale = language.substring(begin, end);
+        }
+      }
 
-  <!--
-   - Configuration property controlling whether to use user agent info for
-   - the user's locale.
-   - Valid values are (case insensitive): y/yes/n/no/true/false/on/off (others
-   - are treated as no).
-   -->
-  <define-configuration-property name="locale.useragent"
-      is-multi-valued="false"/>
-  <set-configuration-property name="locale.useragent" value="N"/>
+      if (locale == null) {
+        // Look for the locale on the web page
+        locale = __gwt_getMetaProperty("locale")
+      }
 
-  <!--
-   - Configuration controlling whether to look for locale information in meta
-   - tags embedded by the server.
-   - Valid values are (case insensitive): y/yes/n/no/true/false/on/off (others
-   - are treated as no).
-   -->
-  <define-configuration-property name="locale.usemeta"
-      is-multi-valued="false"/>
-  <set-configuration-property name="locale.usemeta" value="Y"/>
+      if (locale == null) {
+        // Look for an override computed by other means in the selection script
+        locale = $wnd['__gwt_Locale'];
+      } else {
+        $wnd['__gwt_Locale'] = locale || defaultLocale;
+      }
 
-  <!--
-   - Configuration property defining the order to search for a locale.
-   - Valid values are comma-separated lists of the following values:
-   -   * queryparam
-   -   * meta
-   -   * cookie
-   -   * useragent
-   -->
-  <define-configuration-property name="locale.searchorder"
-      is-multi-valued="false"/>
-  <set-configuration-property name="locale.searchorder"
-      value="queryparam,cookie,meta,useragent"/>
+      if (locale == null) {
+        return defaultLocale;
+      }
 
-  <property-provider name="locale"
-      generator="com.google.gwt.i18n.linker.LocalePropertyProviderGenerator"/>
+      while (!__gwt_isKnownPropertyValue("locale",  locale)) {
+        var lastIndex = locale.lastIndexOf("_");
+        if (lastIndex == -1) {
+          locale = defaultLocale;
+          break;
+        } else {
+          locale = locale.substring(0,lastIndex);
+        }
+      }
+
+      return locale;
+    } catch(e){
+      alert("Unexpected exception in locale detection, using default: " + e);
+      return "default";
+    }
+  ]]>
+  </property-provider>
 
   <generate-with class="com.google.gwt.i18n.rebind.LocalizableGenerator">
     <when-type-assignable class="com.google.gwt.i18n.client.Localizable" />
@@ -95,6 +99,7 @@
       reference the compile-time locale set in the "locale" property.
    -->
   <define-configuration-property name="runtime.locales" is-multi-valued="true"/>
+  <set-configuration-property name="runtime.locales" value=""/>
 
   <!--
       A "real" locale to be served by default (i.e. if the browser either
diff --git a/user/src/com/google/gwt/i18n/client/LocaleInfo.java b/user/src/com/google/gwt/i18n/client/LocaleInfo.java
index 6505de8..ff188cf 100644
--- a/user/src/com/google/gwt/i18n/client/LocaleInfo.java
+++ b/user/src/com/google/gwt/i18n/client/LocaleInfo.java
@@ -69,16 +69,6 @@
   }
 
   /**
-   * Returns the name of the cookie used by GWT to get the locale, or
-   * null if this app was compiled to not use a cookie.
-   * 
-   * @return cookie name or null
-   */
-  public static String getLocaleCookieName() {
-    return instance.infoImpl.getLocaleCookieName();
-  }
-
-  /**
    * Returns the display name of the requested locale in its native locale, if
    * possible. If no native localization is available, the English name will
    * be returned, or as a last resort just the locale name will be returned.  If
@@ -96,16 +86,6 @@
      */
     return instance.infoImpl.getLocaleNativeDisplayName(localeName);
   }
- 
-  /**
-   * Returns the name of the query parameter used by GWT to get the locale, or
-   * null if this app was compiled to not use a query parameter.
-   * 
-   * @return query parameter name or null
-   */
-  public static String getLocaleQueryParamName() {
-    return instance.infoImpl.getLocaleQueryParamName();
-  }
 
   /**
    * Returns true if any locale supported by this build of the app is RTL.
diff --git a/user/src/com/google/gwt/i18n/client/impl/LocaleInfoImpl.java b/user/src/com/google/gwt/i18n/client/impl/LocaleInfoImpl.java
index ce83e1b..92d5ee8 100644
--- a/user/src/com/google/gwt/i18n/client/impl/LocaleInfoImpl.java
+++ b/user/src/com/google/gwt/i18n/client/impl/LocaleInfoImpl.java
@@ -62,13 +62,6 @@
   }
 
   /**
-   * @return the cookie name used for the GWT locale, or null if none.
-   */
-  public String getLocaleCookieName() {
-    return null;
-  }
-
-  /**
    * Returns the current locale name, such as "default, "en_US", etc.
    */
   public String getLocaleName() {
@@ -89,13 +82,6 @@
   }
 
   /**
-   * @return the query parameter name used for the GWT locale, or null if none.
-   */
-  public String getLocaleQueryParamName() {
-    return null;
-  }
-
-  /**
    * @return an implementation of {@link LocalizedNames} for this locale.
    */
   public LocalizedNames getLocalizedNames() {
diff --git a/user/src/com/google/gwt/i18n/linker/LocalePropertyProviderGenerator.java b/user/src/com/google/gwt/i18n/linker/LocalePropertyProviderGenerator.java
deleted file mode 100644
index ecbf23f..0000000
--- a/user/src/com/google/gwt/i18n/linker/LocalePropertyProviderGenerator.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * 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.gwt.i18n.linker;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ConfigurationProperty;
-import com.google.gwt.core.ext.linker.PropertyProviderGenerator;
-import com.google.gwt.user.rebind.SourceWriter;
-import com.google.gwt.user.rebind.StringSourceWriter;
-
-import java.util.SortedSet;
-import java.util.regex.Pattern;
-
-/**
- * Generates a property provider implementation for the "locale" property.
- */
-public class LocalePropertyProviderGenerator implements PropertyProviderGenerator {
-
-  public static final String LOCALE_QUERYPARAM = "locale.queryparam";
-  
-  public static final String LOCALE_COOKIE = "locale.cookie";
-  
-  public static final String LOCALE_SEARCHORDER = "locale.searchorder";
-
-  public static final String LOCALE_USEMETA = "locale.usemeta";
-
-  public static final String LOCALE_USERAGENT = "locale.useragent";
-
-  protected static final Pattern COOKIE_PATTERN = Pattern.compile("^[A-Za-z][A-Za-z0-9_]*$");
-
-  protected static final Pattern QUERYPARAM_PATTERN = Pattern.compile("^[A-Za-z][A-Za-z0-9_]*$");
-
-  /**
-   * Return true when the supplied value represents a true/yes/on value.
-   * 
-   * @param value
-   * @return true if the string represents true/yes/on
-   */
-  protected static boolean isTrue(String value) {
-    return value != null && ("yes".equalsIgnoreCase(value)
-        || "y".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)
-        || "on".equalsIgnoreCase(value));
-  }
-
-  public String generate(TreeLogger logger, SortedSet<String> possibleValues,
-      String fallback, SortedSet<ConfigurationProperty> configProperties)
-      throws UnableToCompleteException {
-    // get relevant config property values
-    String localeQueryParam = null;
-    String localeCookie = null;
-    boolean localeUserAgent = false;
-    boolean localeUseMeta = false;
-    String localeSearchOrder = "queryparam,cookie,meta,useragent";
-    for (ConfigurationProperty configProp : configProperties) {
-      String name = configProp.getName();
-      if (LOCALE_QUERYPARAM.equals(name)) {
-        localeQueryParam = configProp.getValues().get(0);
-        if (localeQueryParam != null && localeQueryParam.length() != 0
-            && !validateQueryParam(localeQueryParam)) {
-          logger.log(TreeLogger.WARN, "Ignoring invalid value of '"
-              + localeQueryParam + "' from '" + LOCALE_QUERYPARAM
-              + "', not a valid query parameter name");
-          localeQueryParam = null;
-        }
-      } else if (LOCALE_COOKIE.equals(name)) {
-          localeCookie = configProp.getValues().get(0);
-          if (localeCookie != null && localeCookie.length() != 0
-              && !validateCookieName(localeCookie)) {
-            logger.log(TreeLogger.WARN, "Ignoring invalid value of '"
-                + localeCookie + "' from '" + LOCALE_COOKIE
-                + "', not a valid cookie name");
-            localeCookie = null;
-          }
-      } else if (LOCALE_USEMETA.equals(name)) {
-        localeUseMeta = isTrue(configProp.getValues().get(0));
-      } else if (LOCALE_USERAGENT.equals(name)) {
-        localeUserAgent = isTrue(configProp.getValues().get(0));
-      } else if (LOCALE_SEARCHORDER.equals(name)) {
-        localeSearchOrder = configProp.getValues().get(0);
-      }
-    }
-    // provide a default for the search order
-    localeSearchOrder = localeSearchOrder.trim();
-    if (localeSearchOrder == null || localeSearchOrder.length() == 0) {
-      localeSearchOrder = "queryparam,cookie,meta,useragent";
-    }
-
-    if (fallback == null) {
-      // TODO(jat): define this in a common place
-      fallback = "default";
-    }
-
-    // build property provider body
-    StringSourceWriter body = new StringSourceWriter();
-    body.println("{");
-    body.indent();
-    body.println("var locale = null;");
-    body.println("var rtlocale = '" + fallback + "';");
-    body.println("try {");
-    for (String method : localeSearchOrder.split(",")) {
-      if ("queryparam".equals(method)) {
-        if (localeQueryParam != null && localeQueryParam.length() > 0) {
-          body.println("if (!locale) {");
-          body.indent();
-          generateQueryParamLookup(logger, body, localeQueryParam);
-          body.outdent();
-          body.println("}");
-        }
-      } else if ("cookie".equals(method)) {
-        if (localeCookie != null && localeCookie.length() > 0) {
-          body.println("if (!locale) {");
-          body.indent();
-          generateCookieLookup(logger, body, localeCookie);
-          body.outdent();
-          body.println("}");
-        }
-      } else if ("meta".equals(method)) {
-        if (localeUseMeta) {
-          body.println("if (!locale) {");
-          body.indent();
-          generateMetaLookup(logger, body);
-          body.outdent();
-          body.println("}");
-        }
-      } else if ("useragent".equals(method)) {
-        if (localeUserAgent) {
-          body.println("if (!locale) {");
-          body.indent();
-          generateUserAgentLookup(logger, body);
-          body.outdent();
-          body.println("}");
-        }
-      } else {
-        logger.log(TreeLogger.WARN, "Ignoring unknown locale lookup method \""
-            + method + "\"");
-        body.println("// ignoring invalid lookup method '" + method + "'");
-      }
-    }
-    body.println("if (!locale) {");
-    body.indent();
-    body.println("locale = $wnd['__gwt_Locale'];");
-    body.outdent();
-    body.println("}");
-    body.println("if (locale) {");
-    body.indent();
-    body.println("rtlocale = locale;");
-    body.outdent();
-    body.println("}");
-    generateInheritanceLookup(logger, body);
-    body.outdent();
-    body.println("} catch (e) {");
-    body.indent();
-    body.println("alert(\"Unexpected exception in locale detection, using "
-        + "default: \" + e);\n");
-    body.outdent();
-    body.println("}");
-    body.println("$wnd['__gwt_Locale'] = rtlocale;");
-    body.println("return locale || \"" + fallback + "\";");
-    body.outdent();
-    body.println("}");
-    return body.toString();
-  }
-
-  /**
-   * Generate JS code that looks up the locale value from a cookie.
-   *
-   * @param logger logger to use
-   * @param body
-   * @param cookieName
-   * @throws UnableToCompleteException
-   */
-  protected void generateCookieLookup(TreeLogger logger, SourceWriter body,
-      String cookieName) throws UnableToCompleteException  {
-    body.println("var cookies = $doc.cookie;");
-    body.println("var idx = cookies.indexOf(\"" + cookieName + "=\");");
-    body.println("if (idx >= 0) {");
-    body.indent();
-    body.println("var end = cookies.indexOf(';', idx);");
-    body.println("if (end < 0) {");
-    body.indent();
-    body.println("end = cookies.length();");
-    body.outdent();
-    body.println("}");
-    body.println("locale = cookies.substring(idx + " + (cookieName.length() + 1)
-        + ", end);");
-    body.outdent();
-    body.println("}");
-  }
-
-  /**
-   * Generate JS code that takes the value of the "locale" variable and finds
-   * parent locales until the value is a supported locale or the default locale.
-   * 
-   * @param logger logger to use
-   * @param body
-   * @throws UnableToCompleteException
-   */
-  protected void generateInheritanceLookup(TreeLogger logger, SourceWriter body)
-      throws UnableToCompleteException  {
-    body.println("while (locale && !__gwt_isKnownPropertyValue(\"locale\", locale)) {");
-    body.indent();
-    body.println("var lastIndex = locale.lastIndexOf(\"_\");");
-    body.println("if (lastIndex < 0) {");
-    body.indent();
-    body.println("locale = null;");
-    body.println("break;");
-    body.outdent();
-    body.println("}");
-    body.println("locale = locale.substring(0, lastIndex);");
-    body.outdent();
-    body.println("}");
-  }
-
-  /**
-   * Generate JS code to fetch the locale from a meta property.
-   *
-   * @param logger logger to use
-   * @param body
-   * @throws UnableToCompleteException
-   */
-  protected void generateMetaLookup(TreeLogger logger, SourceWriter body)
-      throws UnableToCompleteException  {
-    // TODO(jat): do we want to allow customizing the meta property name?
-    body.println("locale = __gwt_getMetaProperty(\"locale\");");
-  }
-
-  /**
-   * Generate JS code to get the locale from a query parameter.
-   *
-   * @param logger logger to use
-   * @param body where to append JS output
-   * @param queryParam the query parameter to use
-   * @throws UnableToCompleteException
-   */
-  protected void generateQueryParamLookup(TreeLogger logger, SourceWriter body,
-      String queryParam) throws UnableToCompleteException  {
-    body.println("var queryParam = location.search;");
-    body.println("var qpStart = queryParam.indexOf(\"" + queryParam + "=\");");
-    body.println("if (qpStart >= 0) {");
-    body.indent();
-    body.println("var value = queryParam.substring(qpStart + "
-        + (queryParam.length() + 1) + ");");
-    body.println("var end = queryParam.indexOf(\"&\", qpStart);");
-    body.println("if (end < 0) {");
-    body.indent();
-    body.println("end = queryParam.length();");
-    body.outdent();
-    body.println("}");
-    body.println("locale = queryParam.substring(qpStart + "
-        + (queryParam.length() + 1) + ", end);");
-    body.outdent();
-    body.println("}");
-  }
-
-  /**
-   * Generate JS code to fetch the locale from the user agent's compile-time
-   * locale.
-   *
-   * @param logger logger to use
-   * @param body
-   * @throws UnableToCompleteException
-   */
-  protected void generateUserAgentLookup(TreeLogger logger, SourceWriter body)
-      throws UnableToCompleteException {
-    body.println("var language = navigator.browserLanguage ? "
-        + "navigator.browserLanguage : navigator.language;");
-    body.println("if (language) {");
-    body.indent();
-    body.println("locale = language.replace(/-/g, \"_\");");
-    body.outdent();
-    body.println();
-  }
-
-  /**
-   * Validate that a name is a valid cookie name.
-   * 
-   * @param cookieName
-   * @return true if cookieName is an acceptable cookie name
-   */
-  protected boolean validateCookieName(String cookieName) {
-    return COOKIE_PATTERN.matcher(cookieName).matches();
-  }
-
-  /**
-   * Validate that a value is a valid query parameter name.
-   * 
-   * @param queryParam
-   * @return true if queryParam is a valid query parameter name. 
-   */
-  protected boolean validateQueryParam(String queryParam) {
-    return QUERYPARAM_PATTERN.matcher(queryParam).matches();
-  }
-}
diff --git a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
index f681eb7..a899a96 100644
--- a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
@@ -17,8 +17,6 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.ext.BadPropertyValueException;
-import com.google.gwt.core.ext.ConfigurationProperty;
 import com.google.gwt.core.ext.Generator;
 import com.google.gwt.core.ext.GeneratorContext;
 import com.google.gwt.core.ext.PropertyOracle;
@@ -28,7 +26,6 @@
 import com.google.gwt.core.ext.typeinfo.NotFoundException;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.i18n.client.impl.LocaleInfoImpl;
-import com.google.gwt.i18n.linker.LocalePropertyProviderGenerator;
 import com.google.gwt.i18n.server.GwtLocaleImpl;
 import com.google.gwt.i18n.shared.GwtLocale;
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
@@ -86,24 +83,6 @@
   }
 
   /**
-   * Generates source representing a string constant that might be null (and
-   * empty strings are treated as null as well).
-   * 
-   * @param value
-   * @return source representation of value
-   */
-  private static String possiblyNullStringConstant(String value) {
-    if (value == null || value.length() == 0) {
-      return "null";
-    }
-    return "\"" + quoteQuotes(value) + "\"";
-  }
-
-  private static String quoteQuotes(String val) {
-    return val.replace("\"", "\\\"");
-  }
-
-  /**
    * Generate an implementation for the given type.
    * 
    * @param logger error logger
@@ -120,25 +99,6 @@
     PropertyOracle propertyOracle = context.getPropertyOracle();
     LocaleUtils localeUtils = LocaleUtils.getInstance(logger, propertyOracle,
         context);
-    String cookieName = null;
-    String queryParamName = null;
-    ConfigurationProperty prop;
-    try {
-      prop = propertyOracle.getConfigurationProperty(
-          LocalePropertyProviderGenerator.LOCALE_COOKIE);
-      cookieName = prop.getValues().get(0);
-    } catch (BadPropertyValueException e) {
-    } catch (IndexOutOfBoundsException e) {
-      // ignore, leaving the value as null
-    }
-    try {
-      prop = propertyOracle.getConfigurationProperty(
-          LocalePropertyProviderGenerator.LOCALE_QUERYPARAM);
-      queryParamName = prop.getValues().get(0);
-    } catch (BadPropertyValueException e) {
-    } catch (IndexOutOfBoundsException e) {
-      // ignore, leaving the value as null
-    }
 
     JClassType targetClass;
     try {
@@ -217,12 +177,6 @@
       writer.println("}");
       writer.println();
       writer.println("@Override");
-      writer.println("public String getLocaleCookieName() {");
-      writer.println("  return " + possiblyNullStringConstant(cookieName)
-          + ";");
-      writer.println("}");
-      writer.println();
-      writer.println("@Override");
       writer.println("public String getLocaleNativeDisplayName(String localeName) {");
       writer.println("  if (GWT.isScript()) {");
       writer.println("    if (nativeDisplayNamesNative == null) {");
@@ -256,12 +210,6 @@
       writer.println("}");
       writer.println();
       writer.println("@Override");
-      writer.println("public String getLocaleQueryParamName() {");
-      writer.println("  return " + possiblyNullStringConstant(queryParamName)
-          + ";");
-      writer.println("}");
-      writer.println();
-      writer.println("@Override");
       writer.println("public boolean hasAnyRTL() {");
       writer.println("  return " + hasAnyRtl + ";");
       writer.println("}");
@@ -431,4 +379,8 @@
     }
     locales.add(locale);
   }
+  
+  private String quoteQuotes(String val) {
+    return val.replace("\"", "\\\"");
+  }
 }
diff --git a/user/test/com/google/gwt/i18n/I18NTest_ar.gwt.xml b/user/test/com/google/gwt/i18n/I18NTest_ar.gwt.xml
index cfc54ae..e00f9d8 100644
--- a/user/test/com/google/gwt/i18n/I18NTest_ar.gwt.xml
+++ b/user/test/com/google/gwt/i18n/I18NTest_ar.gwt.xml
@@ -20,7 +20,4 @@
 	<source path="client"/>
 	<extend-property name="locale" values="ar"/>
 	<set-property name = "locale" value = "ar"/>
-
-  <set-configuration-property name="locale.cookie" value="LOCALE"/>
-  <set-configuration-property name="locale.queryparam" value="arlocale"/>
 </module>
diff --git a/user/test/com/google/gwt/i18n/client/LocaleInfoTest.java b/user/test/com/google/gwt/i18n/client/LocaleInfoTest.java
index c4bae15..52aa6db 100644
--- a/user/test/com/google/gwt/i18n/client/LocaleInfoTest.java
+++ b/user/test/com/google/gwt/i18n/client/LocaleInfoTest.java
@@ -38,17 +38,6 @@
     assertEquals("piglatin_UK_WINDOWS", locale);
   }
 
-  public void testLocaleCookieName() {
-    String cookieName = LocaleInfo.getLocaleCookieName();
-    assertNull("Default locale cooke name should be null", cookieName);
-  }
-
-  public void testLocaleQueryParam() {
-    String queryParam = LocaleInfo.getLocaleQueryParamName();
-    assertEquals("Default locale query param should be 'locale'", "locale",
-        queryParam);
-  }
-
   public void testNativeDisplayNames() {
     // en isn't in the property set for this module so should return null
     String displayName = LocaleInfo.getLocaleNativeDisplayName("en");
diff --git a/user/test/com/google/gwt/i18n/client/LocaleInfo_ar_Test.java b/user/test/com/google/gwt/i18n/client/LocaleInfo_ar_Test.java
index 3b2a15e..6acd948 100644
--- a/user/test/com/google/gwt/i18n/client/LocaleInfo_ar_Test.java
+++ b/user/test/com/google/gwt/i18n/client/LocaleInfo_ar_Test.java
@@ -30,6 +30,11 @@
     return "com.google.gwt.i18n.I18NTest_ar";
   }
 
+  public void testCurrentLocale() {
+    String locale = LocaleInfo.getCurrentLocale().getLocaleName();
+    assertEquals("ar", locale);
+  }
+
   public void testAvailableLocales() {
     String[] locales = LocaleInfo.getAvailableLocaleNames();
     ArrayList<String> localeList = new ArrayList<String>();
@@ -38,23 +43,6 @@
     assertTrue(localeList.contains("default"));
   }
 
-  public void testCurrentLocale() {
-    String locale = LocaleInfo.getCurrentLocale().getLocaleName();
-    assertEquals("ar", locale);
-  }
-
-  public void testLocaleCookieName() {
-    String cookieName = LocaleInfo.getLocaleCookieName();
-    assertEquals("I18N/ar locale cooke name should be 'LOCALE'", "LOCALE",
-        cookieName);
-  }
-
-  public void testLocaleQueryParam() {
-    String queryParam = LocaleInfo.getLocaleQueryParamName();
-    assertEquals("I18N/ar locale query param should be 'arlocale'", "arlocale",
-        queryParam);
-  }
-
   public void testNativeDisplayNames() {
     // verify ar is known
     String displayName = LocaleInfo.getLocaleNativeDisplayName("ar");