diff --git a/core/composer.json b/core/composer.json
index 87e60b4..26030b0 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -14,7 +14,8 @@
     "twig/twig": "1.*@stable",
     "doctrine/common": "2.3.*@stable",
     "guzzle/http": "*",
-    "kriswallsmith/assetic": "1.1.*@alpha"
+    "kriswallsmith/assetic": "1.1.*@alpha",
+    "symfony-cmf/routing": "1.0.*@dev"
   },
   "minimum-stability": "dev"
 }
diff --git a/core/composer.lock b/core/composer.lock
index 1894ab3..d8e8608 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -1,5 +1,5 @@
 {
-    "hash": "5d17aee0bd24c24563c2c864600fc5bd",
+    "hash": "27b5fb7194e0d492c69d372d8ba17b2b",
     "packages": [
         {
             "name": "doctrine/common",
@@ -310,6 +310,56 @@
             ]
         },
         {
+            "name": "symfony-cmf/routing",
+            "version": "dev-master",
+            "target-dir": "Symfony/Cmf/Component/Routing",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony-cmf/Routing",
+                "reference": "1.0.0-alpha3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/symfony-cmf/Routing/archive/1.0.0-alpha3.zip",
+                "reference": "1.0.0-alpha3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2",
+                "symfony/routing": ">=2.1,<2.3-dev",
+                "symfony/http-kernel": ">=2.1,<2.3-dev"
+            },
+            "time": "2012-12-16 17:52:57",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "installation-source": "source",
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Cmf\\Component\\Routing": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony CMF Community",
+                    "homepage": "https://github.com/symfony-cmf/Routing/contributors"
+                }
+            ],
+            "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers",
+            "homepage": "http://cmf.symfony.com",
+            "keywords": [
+                "database",
+                "routing"
+            ]
+        },
+        {
             "name": "symfony/class-loader",
             "version": "dev-master",
             "target-dir": "Symfony/Component/ClassLoader",
@@ -848,6 +898,7 @@
     "stability-flags": {
         "twig/twig": 0,
         "doctrine/common": 0,
-        "kriswallsmith/assetic": 15
+        "kriswallsmith/assetic": 15,
+        "symfony-cmf/routing": 20
     }
 }
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 8300fc3..02c8432 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -10,7 +10,7 @@
 use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterNestedMatchersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterRouteFiltersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterSerializationClassesPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -136,12 +136,32 @@ public function build(ContainerBuilder $container) {
       ->addArgument(new Reference('lock'))
       ->addArgument(new Reference('dispatcher'));
 
+    $container->register('router.request_context', 'Symfony\Component\Routing\RequestContext')
+      ->addMethodCall('fromRequest', array(new Reference('request')));
+    $container->register('router.route_provider', 'Drupal\Core\Routing\RouteProvider')
+      ->addArgument(new Reference('database'));
+    $container->register('router.matcher.final_matcher', 'Drupal\Core\Routing\UrlMatcher');
+    $container->register('router.matcher', 'Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher')
+      ->addArgument(new Reference('router.route_provider'))
+      ->addMethodCall('setFinalMatcher', array(new Reference('router.matcher.final_matcher')));
+    $container->register('router.generator', 'Symfony\Cmf\Component\Routing\ProviderBasedGenerator')
+      ->addArgument(new Reference('router.route_provider'));
+    $container->register('router.dynamic', 'Symfony\Cmf\Component\Routing\DynamicRouter')
+      ->addArgument(new Reference('router.request_context'))
+      ->addArgument(new Reference('router.matcher'))
+      ->addArgument(new Reference('router.generator'));
+
+    $container->register('legacy_generator', 'Drupal\Core\Routing\NullGenerator');
+    $container->register('legacy_url_matcher', 'Drupal\Core\LegacyUrlMatcher');
+    $container->register('legacy_router', 'Symfony\Cmf\Component\Routing\DynamicRouter')
+            ->addArgument(new Reference('router.request_context'))
+            ->addArgument(new Reference('legacy_url_matcher'))
+            ->addArgument(new Reference('legacy_generator'));
 
-    $container->register('matcher', 'Drupal\Core\Routing\ChainMatcher');
-    $container->register('legacy_url_matcher', 'Drupal\Core\LegacyUrlMatcher')
-      ->addTag('chained_matcher');
-    $container->register('nested_matcher', 'Drupal\Core\Routing\NestedMatcher')
-      ->addTag('chained_matcher', array('priority' => 5));
+    $container->register('router', 'Symfony\Cmf\Component\Routing\ChainRouter')
+       ->addMethodCall('setContext', array(new Reference('router.request_context')))
+      ->addMethodCall('add', array(new Reference('legacy_router')))
+      ->addMethodCall('add', array(new Reference('router.dynamic')));
 
     $container
       ->register('cache.path', 'Drupal\Core\Cache\CacheBackendInterface')
@@ -166,26 +186,15 @@ public function build(ContainerBuilder $container) {
     $container->register('password', 'Drupal\Core\Password\PhpassHashedPassword')
       ->addArgument(16);
 
-    // The following services are tagged as 'nested_matcher' services and are
-    // processed in the RegisterNestedMatchersPass compiler pass. Each one
-    // needs to be set on the matcher using a different method, so we use a
-    // tag attribute, 'method', which can be retrieved and passed to the
-    // addMethodCall() method that gets called on the matcher service in the
-    // compiler pass.
-    $container->register('path_matcher', 'Drupal\Core\Routing\PathMatcher')
-      ->addArgument(new Reference('database'))
-      ->addTag('nested_matcher', array('method' => 'setInitialMatcher'));
-    $container->register('http_method_matcher', 'Drupal\Core\Routing\HttpMethodMatcher')
-      ->addTag('nested_matcher', array('method' => 'addPartialMatcher'));
+    // The following services are tagged as 'route_filter' services and are
+    // processed in the RegisterRouteFiltersPass compiler pass.
     $container->register('mime_type_matcher', 'Drupal\Core\Routing\MimeTypeMatcher')
-      ->addTag('nested_matcher', array('method' => 'addPartialMatcher'));
-    $container->register('first_entry_final_matcher', 'Drupal\Core\Routing\FirstEntryFinalMatcher')
-      ->addTag('nested_matcher', array('method' => 'setFinalMatcher'));
+      ->addTag('route_filter');
 
     $container->register('router_processor_subscriber', 'Drupal\Core\EventSubscriber\RouteProcessorSubscriber')
       ->addTag('event_subscriber');
     $container->register('router_listener', 'Symfony\Component\HttpKernel\EventListener\RouterListener')
-      ->addArgument(new Reference('matcher'))
+      ->addArgument(new Reference('router'))
       ->addTag('event_subscriber');
     $container->register('content_negotiation', 'Drupal\Core\ContentNegotiation');
     $container->register('view_subscriber', 'Drupal\Core\EventSubscriber\ViewSubscriber')
@@ -243,7 +252,7 @@ public function build(ContainerBuilder $container) {
       ->addArgument(new Reference('database'));
 
     $container->addCompilerPass(new RegisterMatchersPass());
-    $container->addCompilerPass(new RegisterNestedMatchersPass());
+    $container->addCompilerPass(new RegisterRouteFiltersPass());
     // Add a compiler pass for registering event subscribers.
     $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
     // Add a compiler pass for adding Normalizers and Encoders to Serializer.
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterNestedMatchersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterRouteFiltersPass.php
similarity index 65%
rename from core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterNestedMatchersPass.php
rename to core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterRouteFiltersPass.php
index b245952..be21180 100644
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterNestedMatchersPass.php
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterRouteFiltersPass.php
@@ -14,7 +14,7 @@
 /**
  * Adds services tagged 'nested_matcher' to the tagged_matcher service.
  */
-class RegisterNestedMatchersPass implements CompilerPassInterface {
+class RegisterRouteFiltersPass implements CompilerPassInterface {
 
   /**
    * Adds services tagged 'nested_matcher' to the tagged_matcher service.
@@ -23,13 +23,12 @@ class RegisterNestedMatchersPass implements CompilerPassInterface {
    *   The container to process.
    */
   public function process(ContainerBuilder $container) {
-    if (!$container->hasDefinition('nested_matcher')) {
+    if (!$container->hasDefinition('router.matcher')) {
       return;
     }
-    $nested = $container->getDefinition('nested_matcher');
-    foreach ($container->findTaggedServiceIds('nested_matcher') as $id => $attributes) {
-      $method = $attributes[0]['method'];
-      $nested->addMethodCall($method, array(new Reference($id)));
+    $nested = $container->getDefinition('router.matcher');
+    foreach ($container->findTaggedServiceIds('router_filter') as $id => $attributes) {
+      $nested->addMethodCall('addRouteFilter', array(new Reference($id)));
     }
   }
 }
diff --git a/core/lib/Drupal/Core/Routing/ChainMatcher.php b/core/lib/Drupal/Core/Routing/ChainMatcher.php
deleted file mode 100644
index 23410bf..0000000
--- a/core/lib/Drupal/Core/Routing/ChainMatcher.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\ChainMatcher.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
-use Symfony\Component\Routing\Exception\ResourceNotFoundException;
-use Symfony\Component\Routing\Exception\RouteNotFoundException;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-use Symfony\Component\Routing\RequestContextAwareInterface;
-use Symfony\Component\Routing\RequestContext;
-
-/**
- * Aggregates multiple matchers together in series.
- *
- * The RequestContext is entirely unused. It's included only to satisfy the
- * interface needed for RouterListener.  Hopefully we can remove it later.
- */
-class ChainMatcher implements RequestMatcherInterface, RequestContextAwareInterface {
-
-  /**
-   * Array of RequestMatcherInterface objects to be checked in order.
-   *
-   * @var array
-   */
-  protected $matchers = array();
-
-  /**
-   * Array of RequestMatcherInterface objects, sorted.
-   *
-   * @var type
-   */
-  protected $sortedMatchers = array();
-
-  /**
-   * The request context for this matcher.
-   *
-   * This is unused.  It's just to satisfy the interface.
-   *
-   * @var Symfony\Component\Routing\RequestContext
-   */
-  protected $context;
-
-  /**
-   * Constructor.
-   */
-  public function __construct() {
-    // We will not actually use this object, but it's needed to conform to
-    // the interface.
-    $this->context = new RequestContext();
-  }
-
-  /**
-   * Sets the request context.
-   *
-   * This method is just to satisfy the interface, and is largely vestigial.
-   * The request context object does not contain the information we need, so
-   * we will use the original request object.
-   *
-   * @param Symfony\Component\Routing\RequestContext $context
-   *   The context.
-   */
-  public function setContext(RequestContext $context) {
-    $this->context = $context;
-  }
-
-  /**
-   * Gets the request context.
-   *
-   * This method is just to satisfy the interface, and is largely vestigial.
-   * The request context object does not contain the information we need, so
-   * we will use the original request object.
-   *
-   * @return Symfony\Component\Routing\RequestContext
-   *   The context.
-   */
-  public function getContext() {
-    return $this->context;
-  }
-
-  /**
-   * Matches a request against all queued matchers.
-   *
-   * @param Request $request The request to match
-   *
-   * @return array An array of parameters
-   *
-   * @throws \Symfony\Component\Routing\Exception\ResourceNotFoundException
-   *   If no matching resource could be found
-   * @throws \Symfony\Component\Routing\Exception\MethodNotAllowedException
-   *   If a matching resource was found but the request method is not allowed
-   */
-  public function matchRequest(Request $request) {
-    $methodNotAllowed = null;
-
-    foreach ($this->all() as $matcher) {
-      try {
-        return $matcher->matchRequest($request);
-      } catch (ResourceNotFoundException $e) {
-        // Needs special care
-      } catch (MethodNotAllowedException $e) {
-        $methodNotAllowed = $e;
-      }
-    }
-
-    throw $methodNotAllowed ?: new ResourceNotFoundException("None of the matchers in the chain matched this request.");
-  }
-
-  /**
-    * Adds a Matcher to the index.
-    *
-    * @param MatcherInterface $matcher
-    *   The matcher to add.
-    * @param int $priority
-    *   (optional) The priority of the matcher. Higher number matchers will be checked
-    *   first. Default to 0.
-    */
-  public function add(RequestMatcherInterface $matcher, $priority = 0) {
-    if (empty($this->matchers[$priority])) {
-      $this->matchers[$priority] = array();
-    }
-
-    $this->matchers[$priority][] = $matcher;
-    $this->sortedMatchers = array();
-  }
-
-  /**
-    * Sorts the matchers and flattens them.
-    *
-    * @return array
-    *   An array of RequestMatcherInterface objects.
-    */
-  public function all() {
-    if (empty($this->sortedMatchers)) {
-      $this->sortedMatchers = $this->sortMatchers();
-    }
-
-    return $this->sortedMatchers;
-  }
-
-  /**
-    * Sort matchers by priority.
-    *
-    * The highest priority number is the highest priority (reverse sorting).
-    *
-    * @return \Symfony\Component\Routing\RequestMatcherInterface[]
-    *   An array of Matcher objects in the order they should be used.
-    */
-  protected function sortMatchers() {
-    $sortedMatchers = array();
-    krsort($this->matchers);
-
-    foreach ($this->matchers as $matchers) {
-      $sortedMatchers = array_merge($sortedMatchers, $matchers);
-    }
-
-    return $sortedMatchers;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Routing/CompiledRoute.php b/core/lib/Drupal/Core/Routing/CompiledRoute.php
index c5cdde8..4ebd119 100644
--- a/core/lib/Drupal/Core/Routing/CompiledRoute.php
+++ b/core/lib/Drupal/Core/Routing/CompiledRoute.php
@@ -8,11 +8,12 @@
 namespace Drupal\Core\Routing;
 
 use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\CompiledRoute as SymfonyCompiledRoute;
 
 /**
- * Description of CompiledRoute
+ * A compiled route contains derived information from a route object.
  */
-class CompiledRoute {
+class CompiledRoute extends SymfonyCompiledRoute {
 
   /**
    * The fitness of this route.
@@ -43,14 +44,12 @@ class CompiledRoute {
   protected $route;
 
   /**
-   * The regular expression to match placeholders out of this path.
+   * Constructs a new compiled route object.
    *
-   * @var string
-   */
-  protected $regex;
-
-  /**
-   * Constructs a new CompiledRoute object.
+   * This is a ridiculously long set of constructor parameters, but as this
+   * object is little more than a collection of values it's not a serious
+   * problem. The parent Symfony class does the same, as well, making it
+   * difficult to override differently.
    *
    * @param \Symfony\Component\Routing\Route $route
    *   A original Route instance.
@@ -60,15 +59,30 @@ class CompiledRoute {
    *   The pattern outline for this route.
    * @param int $num_parts
    *   The number of parts in the path.
+   * @param string $staticPrefix
+   *   The static prefix of the compiled route
    * @param string $regex
-   *   The regular expression to match placeholders out of this path.
+   *   The regular expression to use to match this route
+   * @param array $tokens
+   *   An array of tokens to use to generate URL for this route
+   * @param array $pathVariables
+   *   An array of path variables
+   * @param string|null $hostnameRegex
+   *   Hostname regex
+   * @param array $hostnameTokens
+   *   Hostname tokens
+   * @param array $hostnameVariables
+   *   An array of hostname variables
+   * @param array $variables
+   *   An array of variables (variables defined in the path and in the hostname patterns)
    */
-  public function __construct(Route $route, $fit, $pattern_outline, $num_parts, $regex) {
+  public function __construct(Route $route, $fit, $pattern_outline, $num_parts, $staticPrefix, $regex, array $tokens, array $pathVariables, $hostnameRegex = null, array $hostnameTokens = array(), array $hostnameVariables = array(), array $variables = array()) {
+    parent::__construct($staticPrefix, $regex, $tokens, $pathVariables);
+
     $this->route = $route;
     $this->fit = $fit;
     $this->patternOutline = $pattern_outline;
     $this->numParts = $num_parts;
-    $this->regex = $regex;
   }
 
   /**
@@ -110,16 +124,6 @@ public function getPatternOutline() {
   }
 
   /**
-   * Returns the placeholder regex.
-   *
-   * @return string
-   *   The regex to locate placeholders in this pattern.
-   */
-  public function getRegex() {
-    return $this->regex;
-  }
-
-  /**
    * Returns the Route instance.
    *
    * @return Route
diff --git a/core/lib/Drupal/Core/Routing/FinalMatcherInterface.php b/core/lib/Drupal/Core/Routing/FinalMatcherInterface.php
deleted file mode 100644
index 8b85c21..0000000
--- a/core/lib/Drupal/Core/Routing/FinalMatcherInterface.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\FinalMatcherInterface.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * A FinalMatcher returns only one route from a collection of candidate routes.
- */
-interface FinalMatcherInterface {
-
-  /**
-   * Sets the route collection this matcher should use.
-   *
-   * @param \Symfony\Component\Routing\RouteCollection $collection
-   *   The collection against which to match.
-   *
-   * @return \Drupal\Core\Routing\FinalMatcherInterface
-   *   The current matcher.
-   */
-  public function setCollection(RouteCollection $collection);
-
-  /**
-   * Matches a request against multiple routes.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
-   *
-   * @return array
-   *   An array of parameters.
-   */
-  public function matchRequest(Request $request);
-}
diff --git a/core/lib/Drupal/Core/Routing/FirstEntryFinalMatcher.php b/core/lib/Drupal/Core/Routing/FirstEntryFinalMatcher.php
deleted file mode 100644
index cc1adde..0000000
--- a/core/lib/Drupal/Core/Routing/FirstEntryFinalMatcher.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\FirstEntryFinalMatcher.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Final matcher that simply returns the first item in the remaining routes.
- *
- * This class simply matches the first remaining route.
- */
-class FirstEntryFinalMatcher implements FinalMatcherInterface {
-
-  /**
-   * The RouteCollection this matcher should match against.
-   *
-   * @var RouteCollection
-   */
-  protected $routes;
-
-  /**
-   * Sets the route collection this matcher should use.
-   *
-   * @param \Symfony\Component\Routing\RouteCollection $collection
-   *   The collection against which to match.
-   *
-   * @return \Drupal\Core\Routing\FinalMatcherInterface
-   *   The current matcher.
-   */
-  public function setCollection(RouteCollection $collection) {
-    $this->routes = $collection;
-
-    return $this;
-  }
-
-  /**
-   * Implements Drupal\Core\Routing\FinalMatcherInterface::matchRequest().
-   */
-  public function matchRequest(Request $request) {
-    // Return whatever the first route in the collection is.
-    foreach ($this->routes as $name => $route) {
-      $path = '/' . $request->attributes->get('system_path');
-
-      $route->setOption('compiler_class', '\Drupal\Core\Routing\RouteCompiler');
-      $compiled = $route->compile();
-
-      preg_match($compiled->getRegex(), $path, $matches);
-
-      $route->setOption('_name', $name);
-      return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $route));
-    }
-  }
-
-  /**
-   * Get merged default parameters.
-   *
-   * @param array $params
-   *  The parameters.
-   * @param array $defaults
-   *   The defaults.
-   *
-   * @return array
-   *   Merged default parameters.
-   */
-  protected function mergeDefaults($params, $defaults) {
-    $parameters = $defaults;
-    foreach ($params as $key => $value) {
-      if (!is_int($key)) {
-        $parameters[$key] = $value;
-      }
-    }
-
-    return $parameters;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Routing/HttpMethodMatcher.php b/core/lib/Drupal/Core/Routing/HttpMethodMatcher.php
deleted file mode 100644
index 5064353..0000000
--- a/core/lib/Drupal/Core/Routing/HttpMethodMatcher.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\HttpMethodMatcher.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-
-/**
- * This class filters routes based on their HTTP Method.
- */
-class HttpMethodMatcher extends PartialMatcher {
-
-  /**
-   * Matches a request against multiple routes.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
-   *
-   * @return \Symfony\Component\Routing\RouteCollection
-   *   A RouteCollection of matched routes.
-   */
-  public function matchRequestPartial(Request $request) {
-    $possible_methods = array();
-
-    $method = $request->getMethod();
-
-    $collection = new RouteCollection();
-
-    foreach ($this->routes->all() as $name => $route) {
-      // _method could be a |-delimited list of allowed methods, or null. If
-      // null, we accept any method.
-      $allowed_methods = array_filter(explode('|', strtoupper($route->getRequirement('_method'))));
-      if (empty($allowed_methods) || in_array($method, $allowed_methods)) {
-        $collection->add($name, $route);
-      }
-      else {
-        // Build a list of methods that would have matched. Note that we only
-        // need to do this if a route doesn't match, because if even one route
-        // passes then we'll never throw the exception that needs this array.
-        $possible_methods += $allowed_methods;
-      }
-    }
-
-    if (!count($collection->all())) {
-      throw new MethodNotAllowedException(array_unique($possible_methods));
-    }
-
-    return $collection;
-  }
-
-}
-
diff --git a/core/lib/Drupal/Core/Routing/InitialMatcherInterface.php b/core/lib/Drupal/Core/Routing/InitialMatcherInterface.php
deleted file mode 100644
index 53bc8e7..0000000
--- a/core/lib/Drupal/Core/Routing/InitialMatcherInterface.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\InitialMatcherInterface.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-
-/**
- * A PartialMatcher works like a UrlMatcher, but will return multiple candidate routes.
- */
-interface InitialMatcherInterface {
-
-  /**
-   * Matches a request against multiple routes.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
-   *
-   * @return \Symfony\Component\Routing\RouteCollection
-   *   A RouteCollection of matched routes.
-   */
-  public function matchRequestPartial(Request $request);
-}
diff --git a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
index a36bef2..8d86096 100644
--- a/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
+++ b/core/lib/Drupal/Core/Routing/MimeTypeMatcher.php
@@ -10,46 +10,41 @@
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
 use Symfony\Component\Routing\RouteCollection;
+use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface;
 
 /**
  * This class filters routes based on the media type in HTTP Accept headers.
  */
-class MimeTypeMatcher extends PartialMatcher {
+class MimeTypeMatcher implements RouteFilterInterface {
+
 
   /**
-   * Matches a request against multiple routes.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
-   *
-   * @return \Symfony\Component\Routing\RouteCollection
-   *   A RouteCollection of matched routes.
+   * {@inheritDoc}
    */
-  public function matchRequestPartial(Request $request) {
-
+  public function filter(RouteCollection $collection, Request $request) {
     // Generates a list of Symfony formats matching the acceptable MIME types.
     // @todo replace by proper content negotiation library.
     $acceptable_mime_types = $request->getAcceptableContentTypes();
     $acceptable_formats = array_map(array($request, 'getFormat'), $acceptable_mime_types);
 
-    $collection = new RouteCollection();
+    $filtered_collection = new RouteCollection();
 
-    foreach ($this->routes->all() as $name => $route) {
+    foreach ($collection as $name => $route) {
       // _format could be a |-delimited list of supported formats.
       $supported_formats = array_filter(explode('|', $route->getRequirement('_format')));
       // The route partially matches if it doesn't care about format, if it
       // explicitly allows any format, or if one of its allowed formats is
       // in the request's list of acceptable formats.
       if (empty($supported_formats) || in_array('*/*', $acceptable_mime_types) || array_intersect($acceptable_formats, $supported_formats)) {
-        $collection->add($name, $route);
+        $filtered_collection->add($name, $route);
       }
     }
 
-    if (!count($collection)) {
+    if (!count($filtered_collection)) {
       throw new UnsupportedMediaTypeHttpException();
     }
 
-    return $collection;
+    return $filtered_collection;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Routing/NestedMatcher.php b/core/lib/Drupal/Core/Routing/NestedMatcher.php
deleted file mode 100644
index ff53715..0000000
--- a/core/lib/Drupal/Core/Routing/NestedMatcher.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\NestedMatcher.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\Routing\RequestContext;
-use Symfony\Component\HttpFoundation\Request;
-
-/**
- * The nested matcher layers multiple partial matchers together.
- */
-class NestedMatcher implements NestedMatcherInterface {
-
-  /**
-   * The final matcher.
-   *
-   * @var Symfony\Component\Routing\Matcher\RequestMatcherInterface
-   */
-  protected $finalMatcher;
-
-  /**
-   * An array of PartialMatchers.
-   *
-   * @var array
-   */
-  protected $partialMatchers = array();
-
-  /**
-   * Array of PartialMatcherInterface objects, sorted.
-   *
-   * @var type
-   */
-  protected $sortedMatchers = array();
-
-  /**
-   * The initial matcher to match against.
-   *
-   * @var Drupal\core\Routing\InitialMatcherInterface
-   */
-  protected $initialMatcher;
-
-  /**
-   * The request context.
-   *
-   * @var Symfony\Component\Routing\RequestContext
-   */
-  protected $context;
-
-  /**
-   * Adds a partial matcher to the matching plan.
-   *
-   * Partial matchers will be run in the order in which they are added.
-   *
-   * @param \Drupal\Core\Routing\PartialMatcherInterface $matcher
-   *   A partial matcher.
-   * @param int $priority
-   *   (optional) The priority of the matcher. Higher number matchers will be checked
-   *   first. Default to 0.
-   *
-   * @return NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function addPartialMatcher(PartialMatcherInterface $matcher, $priority = 0) {
-    if (empty($this->matchers[$priority])) {
-      $this->matchers[$priority] = array();
-    }
-
-    $this->matchers[$priority][] = $matcher;
-    $this->sortedMatchers = array();
-  }
-
-  /**
-   * Sets the final matcher for the matching plan.
-   *
-   * @param \Drupal\Core\Routing\FinalMatcherInterface $final
-   *   The matcher that will be called last to ensure only a single route is
-   *   found.
-   *
-   * @return \Drupal\Core\Routing\NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function setFinalMatcher(FinalMatcherInterface $final) {
-    $this->finalMatcher = $final;
-
-    return $this;
-  }
-
-  /**
-   * Sets the first matcher for the matching plan.
-   *
-   * Partial matchers will be run in the order in which they are added.
-   *
-   * @param \Drupal\Core\Routing\InitialMatcherInterface $matcher
-   *   An initial matcher.  It is responsible for its own configuration and
-   *   initial route collection
-   *
-   * @return \Drupal\Core\Routing\NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function setInitialMatcher(InitialMatcherInterface $initial) {
-    $this->initialMatcher = $initial;
-
-    return $this;
-  }
-
-  /**
-   * Tries to match a request with a set of routes.
-   *
-   * If the matcher can not find information, it must throw one of the
-   * exceptions documented below.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request to match.
-   *
-   * @return array
-   *   An array of parameters.
-   *
-   * @throws ResourceNotFoundException
-   *   If no matching resource could be found.
-   * @throws MethodNotAllowedException
-   *   If a matching resource was found but the request method is not allowed.
-   */
-  public function matchRequest(Request $request) {
-    $collection = $this->initialMatcher->matchRequestPartial($request);
-
-    foreach ($this->getPartialMatchers() as $matcher) {
-      if ($collection) {
-        $matcher->setCollection($collection);
-      }
-      $collection = $matcher->matchRequestPartial($request);
-    }
-
-    $attributes = $this->finalMatcher->setCollection($collection)->matchRequest($request);
-
-    return $attributes;
-  }
-
-  /**
-    * Sorts the matchers and flattens them.
-    *
-    * @return array
-    *   An array of RequestMatcherInterface objects.
-    */
-  public function getPartialMatchers() {
-    if (empty($this->sortedMatchers)) {
-      $this->sortedMatchers = $this->sortMatchers();
-    }
-
-    return $this->sortedMatchers;
-  }
-
-  /**
-    * Sort matchers by priority.
-    *
-    * The highest priority number is the highest priority (reverse sorting).
-    *
-    * @return \Symfony\Component\Routing\RequestMatcherInterface[]
-    *   An array of Matcher objects in the order they should be used.
-    */
-  protected function sortMatchers() {
-    $sortedMatchers = array();
-    krsort($this->matchers);
-
-    foreach ($this->matchers as $matchers) {
-      $sortedMatchers = array_merge($sortedMatchers, $matchers);
-    }
-
-    return $sortedMatchers;
-  }
-
-  /**
-   * Sets the request context.
-   *
-   * This method is unused. It is here only to satisfy the interface.
-   *
-   * @param \Symfony\Component\Routing\RequestContext $context
-   *   The context
-   */
-  public function setContext(RequestContext $context) {
-    $this->context = $context;
-  }
-
-  /**
-   * Gets the request context.
-   *
-   * This method is unused. It is here only to satisfy the interface.
-   *
-   * @return \Symfony\Component\Routing\RequestContext
-   *   The context
-   */
-  public function getContext() {
-    return $this->context;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Routing/NestedMatcherInterface.php b/core/lib/Drupal/Core/Routing/NestedMatcherInterface.php
deleted file mode 100644
index 6ae0995..0000000
--- a/core/lib/Drupal/Core/Routing/NestedMatcherInterface.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\NestedMatcherInterface.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
-
-/**
- * A NestedMatcher allows for multiple-stage resolution of a route.
- */
-interface NestedMatcherInterface extends RequestMatcherInterface {
-
-  /**
-   * Sets the first matcher for the matching plan.
-   *
-   * Partial matchers will be run in the order in which they are added.
-   *
-   * @param \Drupal\Core\Routing\InitialMatcherInterface $matcher
-   *   An initial matcher.  It is responsible for its own configuration and
-   *   initial route collection
-   *
-   * @return \Drupal\Core\Routing\NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function setInitialMatcher(InitialMatcherInterface $initial);
-
-  /**
-   * Adds a partial matcher to the matching plan.
-   *
-   * Partial matchers will be run in the order in which they are added.
-   *
-   * @param \Drupal\Core\Routing\PartialMatcherInterface $matcher
-   *   A partial matcher.
-   * @param int $priority
-   *   (optional) The priority of the matcher. Higher number matchers will be checked
-   *   first. Default to 0.
-   *
-   * @return NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function addPartialMatcher(PartialMatcherInterface $matcher, $priority = 0);
-
-  /**
-   * Sets the final matcher for the matching plan.
-   *
-   * @param \Drupal\Core\Routing\FinalMatcherInterface $final
-   *   The matcher that will be called last to ensure only a single route is
-   *   found.
-   *
-   * @return \Drupal\Core\Routing\NestedMatcherInterface
-   *   The current matcher.
-   */
-  public function setFinalMatcher(FinalMatcherInterface $final);
-}
diff --git a/core/lib/Drupal/Core/Routing/NullGenerator.php b/core/lib/Drupal/Core/Routing/NullGenerator.php
new file mode 100644
index 0000000..7e72ec3
--- /dev/null
+++ b/core/lib/Drupal/Core/Routing/NullGenerator.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Routing\NullGenerator.
+ */
+
+namespace Drupal\Core\Routing;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+
+/**
+ * No-op implementation of a Url Generator, needed for backward compatibility.
+ */
+class NullGenerator implements UrlGeneratorInterface {
+
+  public function generate($name, $parameters = array(), $absolute = FALSE) {
+    return '';
+    throw new RouteNotFoundException();
+  }
+
+  public function setContext(RequestContext $context) {
+  }
+
+  public function getContext() {
+  }
+}
diff --git a/core/lib/Drupal/Core/Routing/PartialMatcher.php b/core/lib/Drupal/Core/Routing/PartialMatcher.php
deleted file mode 100644
index d28f9ac..0000000
--- a/core/lib/Drupal/Core/Routing/PartialMatcher.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\PartialMatcher.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Utility base class for partial matchers.
- */
-abstract class PartialMatcher implements PartialMatcherInterface {
-
-  /**
-   * The RouteCollection this matcher should match against.
-   *
-   * @var \Symfony\Component\Routing\RouteCollection
-   */
-  protected $routes;
-
-  /**
-   * Sets the route collection this matcher should use.
-   *
-   * @param \Symfony\Component\Routing\RouteCollection $collection
-   *   The collection against which to match.
-   *
-   * @return \Drupal\Core\Routing\PartialMatcherInterface
-   *   The current matcher.
-   */
-  public function setCollection(RouteCollection $collection) {
-    $this->routes = $collection;
-
-    return $this;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Routing/PartialMatcherInterface.php b/core/lib/Drupal/Core/Routing/PartialMatcherInterface.php
deleted file mode 100644
index 0d180c6..0000000
--- a/core/lib/Drupal/Core/Routing/PartialMatcherInterface.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Routing\PathMatcherInterface.
- */
-
-namespace Drupal\Core\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * A PartialMatcher works like a UrlMatcher, but will return multiple candidate routes.
- */
-interface PartialMatcherInterface {
-
-  /**
-   * Sets the route collection this matcher should use.
-   *
-   * @param \Symfony\Component\Routing\RouteCollection $collection
-   *   The collection against which to match.
-   *
-   * @return \Drupal\Core\Routing\PartialMatcherInterface
-   *   The current matcher.
-   */
-  public function setCollection(RouteCollection $collection);
-
-  /**
-   * Matches a request against multiple routes.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
-   *
-   * @return \Symfony\Component\Routing\RouteCollection
-   *   A RouteCollection of matched routes.
-   */
-  public function matchRequestPartial(Request $request);
-}
diff --git a/core/lib/Drupal/Core/Routing/RouteCompiler.php b/core/lib/Drupal/Core/Routing/RouteCompiler.php
index 2585d74..e6095d8 100644
--- a/core/lib/Drupal/Core/Routing/RouteCompiler.php
+++ b/core/lib/Drupal/Core/Routing/RouteCompiler.php
@@ -9,11 +9,12 @@
 
 use Symfony\Component\Routing\RouteCompilerInterface;
 use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCompiler as SymfonyRouteCompiler;
 
 /**
  * Compiler to generate derived information from a Route necessary for matching.
  */
-class RouteCompiler implements RouteCompilerInterface {
+class RouteCompiler extends SymfonyRouteCompiler implements RouteCompilerInterface {
 
   /**
    * The maximum number of path elements for a route pattern;
@@ -26,8 +27,31 @@ class RouteCompiler implements RouteCompilerInterface {
   const REGEX_DELIMITER = '#';
 
   /**
+   * Compiler for the Symfony route compilation data.
+   *
+   * @var \Symfony\Component\Routing\RouteCompiler
+   */
+  protected $symfonyCompiler;
+
+  /**
+   * Constructs a new RouteCompiler.
+   *
+   * Normally putting a dependent object in here like this would be a no-no,
+   * but Symfony's route compiler insists on class injection rather than object
+   * injection so we are given no choice.
+   */
+  public function __construct() {
+    //$this->symfonyCompiler = new SymfonyRouteCompiler();
+  }
+
+  /**
    * Compiles the current route instance.
    *
+   * Because so much of the parent class is private, we need to call the parent
+   * class's compile() method and then dissect its return value to build our
+   * new compiled object.  If upstream gets refactored so we can subclass more
+   * easily then this may not be necessary.
+   *
    * @param \Symfony\Component\Routing\Route $route
    *   A Route instance.
    *
@@ -36,142 +60,29 @@ class RouteCompiler implements RouteCompilerInterface {
    */
   public function compile(Route $route) {
 
-    $stripped_path = $this->getPathWithoutDefaults($route);
+    $symfony_compiled = parent::compile($route);
 
+    // The Drupal-specific compiled information.
+    $stripped_path = $this->getPathWithoutDefaults($route);
     $fit = $this->getFit($stripped_path);
-
     $pattern_outline = $this->getPatternOutline($stripped_path);
-
     $num_parts = count(explode('/', trim($pattern_outline, '/')));
 
-    $regex = $this->getRegex($route, $route->getPattern());
-
-    return new CompiledRoute($route, $fit, $pattern_outline, $num_parts, $regex);
-  }
-
-  /**
-   * Generates a regular expression that will match this pattern.
-   *
-   * This regex can be used in preg_match() to extract values inside {}.
-   *
-   * This algorithm was lifted directly from Symfony's RouteCompiler class.
-   * It is not factored out nicely there, so we cannot simply subclass it.
-   * @todo Refactor Symfony's RouteCompiler so that it's useful to subclass.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route object.
-   * @param string $pattern
-   *   The pattern for which we want a matching regex.
-   *
-   * @return string
-   *   A regular expression that will match a path against this route.
-   *
-   * @throws \LogicException
-   */
-  public function getRegex(Route $route, $pattern) {
-    $len = strlen($pattern);
-    $tokens = array();
-    $variables = array();
-    $pos = 0;
-    preg_match_all('#.\{(\w+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
-    foreach ($matches as $match) {
-      if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
-        $tokens[] = array('text', $text);
-      }
-
-      $pos = $match[0][1] + strlen($match[0][0]);
-      $var = $match[1][0];
-
-      if ($req = $route->getRequirement($var)) {
-        $regexp = $req;
-      }
-      else {
-        // Use the character preceding the variable as a separator
-        $separators = array($match[0][0][0]);
-
-        if ($pos !== $len) {
-          // Use the character following the variable as the separator when available
-          $separators[] = $pattern[$pos];
-        }
-        $regexp = sprintf('[^%s]+', preg_quote(implode('', array_unique($separators)), self::REGEX_DELIMITER));
-      }
-
-      $tokens[] = array('variable', $match[0][0][0], $regexp, $var);
-
-      if (in_array($var, $variables)) {
-        throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $route->getPattern(), $var));
-      }
-
-      $variables[] = $var;
-    }
-
-    if ($pos < $len) {
-      $tokens[] = array('text', substr($pattern, $pos));
-    }
-
-    // find the first optional token
-    $first_optional = INF;
-    for ($i = count($tokens) - 1; $i >= 0; $i--) {
-        $token = $tokens[$i];
-        if ('variable' === $token[0] && $route->hasDefault($token[3])) {
-            $first_optional = $i;
-        } else {
-            break;
-        }
-    }
-
-    // compute the matching regexp
-    $regexp = '';
-    for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) {
-        $regexp .= $this->computeRegexp($tokens, $i, $first_optional);
-    }
-
-    return self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s';
-  }
-
-  /**
-   * Computes the regexp used to match a specific token. It can be static text or a subpattern.
-   *
-   * @param array $tokens
-   *   The route tokens
-   * @param integer $index
-   *   The index of the current token
-   * @param integer $first_optional
-   *   The index of the first optional token
-   *
-   * @return string
-   *   The regexp pattern for a single token
-   */
-  private function computeRegexp(array $tokens, $index, $first_optional) {
-    $token = $tokens[$index];
-    if ('text' === $token[0]) {
-      // Text tokens
-      return preg_quote($token[1], self::REGEX_DELIMITER);
-    }
-    else {
-      // Variable tokens
-      if (0 === $index && 0 === $first_optional) {
-        // When the only token is an optional variable token, the separator is
-        // required.
-        return sprintf('%s(?<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
-      }
-      else {
-        $regexp = sprintf('%s(?<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]);
-        if ($index >= $first_optional) {
-          // Enclose each optional token in a subpattern to make it optional.
-          // "?:" means it is non-capturing, i.e. the portion of the subject
-          // string that matched the optional subpattern is not passed back.
-          $regexp = "(?:$regexp";
-          $nbTokens = count($tokens);
-          if ($nbTokens - 1 == $index) {
-            // Close the optional subpatterns.
-            $regexp .= str_repeat(")?", $nbTokens - $first_optional - (0 === $first_optional ? 1 : 0));
-          }
-        }
-
-        return $regexp;
-      }
-    }
+    return new CompiledRoute(
+      $route,
+      $fit,
+      $pattern_outline,
+      $num_parts,
+      // These are the Symfony compiled parts.
+      $symfony_compiled->getStaticPrefix(),
+      $symfony_compiled->getRegex(),
+      $symfony_compiled->getTokens(),
+      $symfony_compiled->getPathVariables(),
+      $symfony_compiled->getHostnameRegex(),
+      $symfony_compiled->getHostnameTokens(),
+      $symfony_compiled->getHostnameVariables(),
+      $symfony_compiled->getVariables()
+      );
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Routing/PathMatcher.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
similarity index 54%
rename from core/lib/Drupal/Core/Routing/PathMatcher.php
rename to core/lib/Drupal/Core/Routing/RouteProvider.php
index 9b5bd5e..f2aea92 100644
--- a/core/lib/Drupal/Core/Routing/PathMatcher.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -2,21 +2,22 @@
 
 /**
  * @file
- * Definition of Drupal\Core\Routing\PathMatcher.
+ * Contains Drupal\Core\Routing\RouteProvider.
  */
 
 namespace Drupal\Core\Routing;
 
+use Symfony\Cmf\Component\Routing\RouteProviderInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\RouteCollection;
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
-use Drupal\Core\Database\Connection;
+use \Drupal\Core\Database\Connection;
 
 /**
- * Initial matcher to match a route against a built database, by path.
+ * A Route Provider front-end for all Drupal-stored routes.
  */
-class PathMatcher implements InitialMatcherInterface {
+class RouteProvider implements RouteProviderInterface {
 
   /**
    * The database connection from which to read route information.
@@ -46,15 +47,29 @@ public function __construct(Connection $connection, $table = 'router') {
   }
 
   /**
-   * Matches a request against multiple routes.
+   * Finds routes that may potentially match the request.
    *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A Request object against which to match.
+   * This may return a mixed list of class instances, but all routes returned
+   * must extend the core symfony route. The classes may also implement
+   * RouteObjectInterface to link to a content document.
    *
-   * @return \Symfony\Component\Routing\RouteCollection
-   *   A RouteCollection of matched routes.
+   * This method may not throw an exception based on implementation specific
+   * restrictions on the url. That case is considered a not found - returning
+   * an empty array. Exceptions are only used to abort the whole request in
+   * case something is seriously broken, like the storage backend being down.
+   *
+   * Note that implementations may not implement an optimal matching
+   * algorithm, simply a reasonable first pass.  That allows for potentially
+   * very large route sets to be filtered down to likely candidates, which
+   * may then be filtered in memory more completely.
+   *
+   * @param Request $request A request against which to match.
+   *
+   * @return \Symfony\Component\Routing\RouteCollection with all urls that
+   *      could potentially match $request. Empty collection if nothing can
+   *      match.
    */
-  public function matchRequestPartial(Request $request) {
+  public function getRouteCollectionForRequest(Request $request) {
 
     // The 'system_path' has language prefix stripped and path alias resolved,
     // whereas getPathInfo() returns the requested path. In Drupal, the request
@@ -97,6 +112,57 @@ public function matchRequestPartial(Request $request) {
   }
 
   /**
+   * Find the route using the provided route name (and parameters)
+   *
+   * @param string $name the route name to fetch
+   * @param array $parameters the parameters as they are passed to the
+   *      UrlGeneratorInterface::generate call
+   *
+   * @return \Symfony\Component\Routing\Route
+   *
+   * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException if
+   *      there is no route with that name in this repository
+   */
+  public function getRouteByName($name, $parameters = array()) {
+    $routes = $this->getRoutesByNames(array($name), $parameters);
+    if (empty($routes)) {
+      throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name));
+    }
+
+    return reset($routes);
+  }
+
+  /**
+   * Find many routes by their names using the provided list of names
+   *
+   * Note that this method may not throw an exception if some of the routes
+   * are not found. It will just return the list of those routes it found.
+   *
+   * This method exists in order to allow performance optimizations. The
+   * simple implementation could be to just repeatedly call
+   * $this->getRouteByName()
+   *
+   * @param array $names the list of names to retrieve
+   * @param array $parameters the parameters as they are passed to the
+   *      UrlGeneratorInterface::generate call. (Only one array, not one for
+   *      each entry in $names.
+   *
+   * @return \Symfony\Component\Routing\Route[] iterable thing with the keys
+   *      the names of the $names argument.
+   */
+  public function getRoutesByNames($names, $parameters = array()) {
+    $result = $this->connection->query('SELECT name, route FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN :names', array(':names' => $names));
+    $routes = $result->fetchAllKeyed();
+
+    $return = array();
+    foreach ($routes as $name => $route) {
+      $return[$name] = unserialize($route);
+    }
+
+    return $return;
+  }
+
+  /**
    * Returns an array of path pattern outlines that could match the path parts.
    *
    * @param array $parts
@@ -145,4 +211,5 @@ public function getCandidateOutlines(array $parts) {
     }
     return $ancestors;
   }
+
 }
diff --git a/core/lib/Drupal/Core/Routing/UrlMatcher.php b/core/lib/Drupal/Core/Routing/UrlMatcher.php
new file mode 100644
index 0000000..1e302bd
--- /dev/null
+++ b/core/lib/Drupal/Core/Routing/UrlMatcher.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Drupal\Core\Routing;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Cmf\Component\Routing\NestedMatcher\UrlMatcher as BaseUrlMatcher;
+
+/**
+ * Drupal-specific URL Matcher; handles the Drupal "system path" mapping.
+ */
+class UrlMatcher extends BaseUrlMatcher {
+
+  public function __construct() {}
+
+  public function finalMatch(RouteCollection $collection, Request $request) {
+    $this->routes = $collection;
+    $context = new RequestContext();
+    $context->fromRequest($request);
+    $this->setContext($context);
+    return $this->match('/' . $request->attributes->get('system_path'));
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/ChainMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/ChainMatcherTest.php
deleted file mode 100644
index c6b28cc..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/ChainMatcherTest.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Routing\ChainMatcherTest.
- */
-
-namespace Drupal\system\Tests\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
-use Symfony\Component\Routing\Exception\ResourceNotFoundException;
-use Symfony\Component\Routing\Exception\RouteNotFoundException;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-
-use Drupal\simpletest\UnitTestBase;
-use Drupal\Core\Routing\ChainMatcher;
-
-use Exception;
-
-/**
- * Basic tests for the ChainMatcher.
- */
-class ChainMatcherTest extends UnitTestBase {
-  
-  public static function getInfo() {
-    return array(
-      'name' => 'Chain matcher tests',
-      'description' => 'Confirm that the chain matcher is working correctly.',
-      'group' => 'Routing',
-    );
-  }
-
-  /**
-   * Confirms that the expected exception is thrown.
-   */
-  public function testMethodNotAllowed() {
-
-    $chain = new ChainMatcher();
-
-    $method_not_allowed = new MockMatcher(function(Request $request) {
-      throw new MethodNotAllowedException(array('POST'));
-    });
-
-    try {
-      $chain->add($method_not_allowed);
-      $chain->matchRequest(Request::create('my/path'));
-    }
-    catch (MethodNotAllowedException $e) {
-      $this->pass('Correct exception thrown.');
-    }
-    catch (Exception $e) {
-      $this->fail('Incorrect exception thrown: ' . get_class($e));
-    }
-  }
-
-  /**
-   * Confirms that the expected exception is thrown.
-   */
-  public function testRequestNotFound() {
-
-    $chain = new ChainMatcher();
-
-    $resource_not_found = new MockMatcher(function(Request $request) {
-      throw new ResourceNotFoundException();
-    });
-
-    try {
-      $chain->add($resource_not_found);
-      $chain->matchRequest(Request::create('my/path'));
-    }
-    catch (ResourceNotFoundException $e) {
-      $this->pass('Correct exception thrown.');
-    }
-    catch (Exception $e) {
-      $this->fail('Incorrect exception thrown: ' . get_class($e));
-    }
-  }
-
-  /**
-   * Confirms that the expected exception is thrown.
-   */
-  public function testRequestFound() {
-
-    $chain = new ChainMatcher();
-
-    $method_not_allowed = new MockMatcher(function(Request $request) {
-      throw new MethodNotAllowedException(array('POST'));
-    });
-
-    $resource_not_found = new MockMatcher(function(Request $request) {
-      throw new ResourceNotFoundException();
-    });
-
-    $found_data = new MockMatcher(function(Request $request) {
-      return array('_controller' => 'foo');
-    });
-
-    try {
-      $chain->add($method_not_allowed);
-      $chain->add($resource_not_found);
-      $chain->add($found_data);
-      $request = Request::create('my/path');
-      $attributes = $chain->matchRequest($request);
-      $this->assertEqual($attributes['_controller'], 'foo', 'Correct attributes returned.');
-    }
-    catch (Exception $e) {
-      $this->fail('Exception thrown when a match should have been successful: ' . get_class($e));
-    }
-  }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/FirstEntryFinalMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/FirstEntryFinalMatcherTest.php
deleted file mode 100644
index c44a492..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/FirstEntryFinalMatcherTest.php
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Routing\NestedMatcherTest.
- */
-
-namespace Drupal\system\Tests\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-
-use Drupal\simpletest\UnitTestBase;
-use Drupal\Core\Routing\HttpMethodMatcher;
-use Drupal\Core\Routing\NestedMatcher;
-use Drupal\Core\Routing\FirstEntryFinalMatcher;
-
-use Exception;
-
-/**
- * Basic tests for the NestedMatcher class.
- */
-class FirstEntryFinalMatcherTest extends UnitTestBase {
-
-  /**
-   * A collection of shared fixture data for tests.
-   *
-   * @var RoutingFixtures
-   */
-  protected $fixtures;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'FirstEntryFinalMatcher tests',
-      'description' => 'Confirm that the FirstEntryFinalMatcher is working properly.',
-      'group' => 'Routing',
-    );
-  }
-
-  function __construct($test_id = NULL) {
-    parent::__construct($test_id);
-
-    $this->fixtures = new RoutingFixtures();
-  }
-
-  /**
-   * Confirms the final matcher returns correct attributes for static paths.
-   */
-  public function testFinalMatcherStatic() {
-
-    $collection = new RouteCollection();
-    $collection->add('route_a', new Route('/path/one', array(
-      '_controller' => 'foo',
-    )));
-
-    $request = Request::create('/path/one', 'GET');
-
-    $matcher = new FirstEntryFinalMatcher();
-    $matcher->setCollection($collection);
-    $attributes = $matcher->matchRequest($request);
-
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_a', 'The correct matching route was found.');
-    $this->assertEqual($attributes['_controller'], 'foo', 'The correct controller was found.');
-  }
-
-  /**
-   * Confirms the final matcher returns correct attributes for pattern paths.
-   */
-  public function testFinalMatcherPattern() {
-
-    $collection = new RouteCollection();
-    $collection->add('route_a', new Route('/path/one/{value}', array(
-      '_controller' => 'foo',
-    )));
-
-    $request = Request::create('/path/one/narf', 'GET');
-    $request->attributes->set('system_path', 'path/one/narf');
-
-    $matcher = new FirstEntryFinalMatcher();
-    $matcher->setCollection($collection);
-    $attributes = $matcher->matchRequest($request);
-
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_a', 'The correct matching route was found.');
-    $this->assertEqual($attributes['_controller'], 'foo', 'The correct controller was found.');
-    $this->assertEqual($attributes['value'], 'narf', 'Required placeholder value found.');
-  }
-
-  /**
-   * Confirms the final matcher returns correct attributes with default values.
-   */
-  public function testFinalMatcherPatternDefalts() {
-
-    $collection = new RouteCollection();
-    $collection->add('route_a', new Route('/path/one/{value}', array(
-      '_controller' => 'foo',
-      'value' => 'poink'
-    )));
-
-    $request = Request::create('/path/one', 'GET');
-    $request->attributes->set('system_path', 'path/one');
-
-    $matcher = new FirstEntryFinalMatcher();
-    $matcher->setCollection($collection);
-    $attributes = $matcher->matchRequest($request);
-
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_a', 'The correct matching route was found.');
-    $this->assertEqual($attributes['_controller'], 'foo', 'The correct controller was found.');
-    $this->assertEqual($attributes['value'], 'poink', 'Optional placeholder value used default.');
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/HttpMethodMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/HttpMethodMatcherTest.php
deleted file mode 100644
index 8055743..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/HttpMethodMatcherTest.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Routing\HttpMethodMMatcherTest.
- */
-
-namespace Drupal\system\Tests\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-
-use Drupal\simpletest\UnitTestBase;
-use Drupal\Core\Routing\HttpMethodMatcher;
-use Drupal\Core\Routing\NestedMatcher;
-use Drupal\Core\Routing\FirstEntryFinalMatcher;
-
-use Exception;
-
-/**
- * Basic tests for the HttpMethodMatcher class.
- */
-class HttpMethodMatcherTest extends UnitTestBase {
-
-  /**
-   * A collection of shared fixture data for tests.
-   *
-   * @var RoutingFixtures
-   */
-  protected $fixtures;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Partial matcher HTTP Method tests',
-      'description' => 'Confirm that the Http Method partial matcher is functioning properly.',
-      'group' => 'Routing',
-    );
-  }
-
-  function __construct($test_id = NULL) {
-    parent::__construct($test_id);
-
-    $this->fixtures = new RoutingFixtures();
-  }
-
-  /**
-   * Confirms that the HttpMethod matcher matches properly.
-   */
-  public function testFilterRoutes() {
-
-    $matcher = new HttpMethodMatcher();
-    $matcher->setCollection($this->fixtures->sampleRouteCollection());
-
-    $routes = $matcher->matchRequestPartial(Request::create('path/one', 'GET'));
-
-    $this->assertEqual(count($routes->all()), 4, 'The correct number of routes was found.');
-    $this->assertNotNull($routes->get('route_a'), 'The first matching route was found.');
-    $this->assertNull($routes->get('route_b'), 'The non-matching route was not found.');
-    $this->assertNotNull($routes->get('route_c'), 'The second matching route was found.');
-    $this->assertNotNull($routes->get('route_d'), 'The all-matching route was found.');
-    $this->assertNotNull($routes->get('route_e'), 'The multi-matching route was found.');
-  }
-
-  /**
-   * Confirms we can nest multiple partial matchers.
-   */
-  public function testNestedMatcher() {
-
-    $matcher = new NestedMatcher();
-
-    $matcher->setInitialMatcher(new MockPathMatcher($this->fixtures->sampleRouteCollection()));
-    $matcher->addPartialMatcher(new HttpMethodMatcher());
-    $matcher->setFinalMatcher(new FirstEntryFinalMatcher());
-
-    $request = Request::create('/path/one', 'GET');
-
-    $attributes = $matcher->matchRequest($request);
-
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_a', 'The correct matching route was found.');
-  }
-
-  /**
-   * Confirms that the HttpMethod matcher throws an exception for no-route.
-   */
-  public function testNoRouteFound() {
-    $matcher = new HttpMethodMatcher();
-
-    // Remove the sample route that would match any method.
-    $routes = $this->fixtures->sampleRouteCollection();
-    $routes->remove('route_d');
-
-    $matcher->setCollection($routes);
-
-    try {
-      $routes = $matcher->matchRequestPartial(Request::create('path/one', 'DELETE'));
-      $this->fail(t('No exception was thrown.'));
-    }
-    catch (Exception $e) {
-      $this->assertTrue($e instanceof MethodNotAllowedException, 'The correct exception was thrown.');
-    }
-
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/MimeTypeMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/MimeTypeMatcherTest.php
index 05f8d42..07bb859 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/MimeTypeMatcherTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Routing/MimeTypeMatcherTest.php
@@ -47,52 +47,34 @@ function __construct($test_id = NULL) {
   public function testFilterRoutes() {
 
     $matcher = new MimeTypeMatcher();
-    $matcher->setCollection($this->fixtures->sampleRouteCollection());
+    $collection = $this->fixtures->sampleRouteCollection();
 
     // Tests basic JSON request.
     $request = Request::create('path/two', 'GET');
     $request->headers->set('Accept', 'application/json, text/xml;q=0.9');
-    $routes = $matcher->matchRequestPartial($request);
-    $this->assertEqual(count($routes->all()), 4, 'The correct number of routes was found.');
+    $routes = $matcher->filter($collection, $request);
+    $this->assertEqual(count($routes), 4, 'The correct number of routes was found.');
     $this->assertNotNull($routes->get('route_c'), 'The json route was found.');
     $this->assertNull($routes->get('route_e'), 'The html route was not found.');
 
     // Tests JSON request with alternative JSON MIME type Accept header.
     $request = Request::create('path/two', 'GET');
     $request->headers->set('Accept', 'application/x-json, text/xml;q=0.9');
-    $routes = $matcher->matchRequestPartial($request);
-    $this->assertEqual(count($routes->all()), 4, 'The correct number of routes was found.');
+    $routes = $matcher->filter($collection, $request);
+    $this->assertEqual(count($routes), 4, 'The correct number of routes was found.');
     $this->assertNotNull($routes->get('route_c'), 'The json route was found.');
     $this->assertNull($routes->get('route_e'), 'The html route was not found.');
 
     // Tests basic HTML request.
     $request = Request::create('path/two', 'GET');
     $request->headers->set('Accept', 'text/html, text/xml;q=0.9');
-    $routes = $matcher->matchRequestPartial($request);
-    $this->assertEqual(count($routes->all()), 4, 'The correct number of routes was found.');
+    $routes = $matcher->filter($collection, $request);
+    $this->assertEqual(count($routes), 4, 'The correct number of routes was found.');
     $this->assertNull($routes->get('route_c'), 'The json route was not found.');
     $this->assertNotNull($routes->get('route_e'), 'The html route was found.');
   }
 
   /**
-   * Confirms we can nest multiple partial matchers.
-   */
-  public function testNestedMatcher() {
-
-    $matcher = new NestedMatcher();
-
-    $matcher->setInitialMatcher(new MockPathMatcher($this->fixtures->sampleRouteCollection()));
-    $matcher->addPartialMatcher(new MimeTypeMatcher());
-    $matcher->setFinalMatcher(new FirstEntryFinalMatcher());
-
-    $request = Request::create('/path/two', 'GET');
-    $request->headers->set('Accept', 'text/html, text/xml;q=0.9');
-
-    $attributes = $matcher->matchRequest($request);
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_e', 'The correct matching route was found.');
-  }
-
-  /**
    * Confirms that the MimeTypeMatcher matcher throws an exception for no-route.
    */
   public function testNoRouteFound() {
@@ -105,12 +87,10 @@ public function testNoRouteFound() {
     $routes->remove('route_c');
     $routes->remove('route_d');
 
-    $matcher->setCollection($routes);
-
     try {
       $request = Request::create('path/two', 'GET');
       $request->headers->set('Accept', 'application/json, text/xml;q=0.9');
-      $routes = $matcher->matchRequestPartial($request);
+      $routes = $matcher->filter($routes, $request);
       $this->fail(t('No exception was thrown.'));
     }
     catch (UnsupportedMediaTypeHttpException $e) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/MockPathMatcher.php b/core/modules/system/lib/Drupal/system/Tests/Routing/MockPathMatcher.php
deleted file mode 100644
index 1592cbf..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/MockPathMatcher.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-namespace Drupal\system\Tests\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-
-use Drupal\Core\Routing\InitialMatcherInterface;
-
-/**
- * Provides a mock path matcher.
- */
-class MockPathMatcher implements InitialMatcherInterface {
-
-  /**
-   * Routes to be matched.
-   *
-   * @var Symfony\Component\Routing\RouteCollection
-   */
-  protected $routes;
-
-  /**
-   * Construct the matcher given the route collection.
-   *
-   * @param Symfony\Component\Routing\RouteCollection $routes
-   *   The routes being matched.
-   */
-  public function __construct(RouteCollection $routes) {
-    $this->routes = $routes;
-  }
-
-  /**
-   * Matches a request against multiple routes.
-   *
-   * @param Request $request
-   *   A Request object against which to match.
-   *
-   * @return RouteCollection
-   *   A RouteCollection of matched routes.
-   */
-  public function matchRequestPartial(Request $request) {
-    // For now for testing we'll just do a straight string match.
-
-    $path = $request->getPathInfo();
-
-    $return = new RouteCollection();
-
-    foreach ($this->routes as $name => $route) {
-      if ($route->getPattern() == $path) {
-        $return->add($name, $route);
-      }
-    }
-
-    return $return;
-  }
-
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/NestedMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/NestedMatcherTest.php
deleted file mode 100644
index de29538..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/NestedMatcherTest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Routing\NestedMatcherTest.
- */
-
-namespace Drupal\system\Tests\Routing;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-
-use Drupal\simpletest\UnitTestBase;
-use Drupal\Core\Routing\HttpMethodMatcher;
-use Drupal\Core\Routing\NestedMatcher;
-use Drupal\Core\Routing\FirstEntryFinalMatcher;
-
-use Exception;
-
-/**
- * Basic tests for the NestedMatcher class.
- */
-class NestedMatcherTest extends UnitTestBase {
-
-  /**
-   * A collection of shared fixture data for tests.
-   *
-   * @var RoutingFixtures
-   */
-  protected $fixtures;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'NestedMatcher tests',
-      'description' => 'Confirm that the NestedMatcher system is working properly.',
-      'group' => 'Routing',
-    );
-  }
-
-  function __construct($test_id = NULL) {
-    parent::__construct($test_id);
-
-    $this->fixtures = new RoutingFixtures();
-  }
-
-  /**
-   * Confirms we can nest multiple partial matchers.
-   */
-  public function testNestedMatcher() {
-
-    $matcher = new NestedMatcher();
-
-    $matcher->setInitialMatcher(new MockPathMatcher($this->fixtures->sampleRouteCollection()));
-    $matcher->addPartialMatcher(new HttpMethodMatcher(), 1);
-    $matcher->setFinalMatcher(new FirstEntryFinalMatcher());
-
-    $request = Request::create('/path/one', 'GET');
-
-    $attributes = $matcher->matchRequest($request);
-
-    $this->assertEqual($attributes['_route']->getOption('_name'), 'route_a', 'The correct matching route was found.');
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/PathMatcherTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php
similarity index 81%
rename from core/modules/system/lib/Drupal/system/Tests/Routing/PathMatcherTest.php
rename to core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php
index 6769107..9ebd2ed 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Routing/PathMatcherTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouteProviderTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\system\Tests\Routing\PartialMatcherTest.
+ * Definition of Drupal\system\Tests\Routing\RouteProviderTest.
  */
 
 namespace Drupal\system\Tests\Routing;
@@ -13,16 +13,16 @@
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
 use Drupal\simpletest\UnitTestBase;
-use Drupal\Core\Routing\PathMatcher;
+use Drupal\Core\Routing\RouteProvider;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Routing\MatcherDumper;
 
 use Exception;
 
 /**
- * Basic tests for the UrlMatcherDumper.
+ * Basic tests for the RouteProvider.
  */
-class PathMatcherTest extends UnitTestBase {
+class RouteProviderTest extends UnitTestBase {
 
   /**
    * A collection of shared fixture data for tests.
@@ -33,8 +33,8 @@ class PathMatcherTest extends UnitTestBase {
 
   public static function getInfo() {
     return array(
-      'name' => 'Path matcher tests',
-      'description' => 'Confirm that the path matching library is working correctly.',
+      'name' => 'Route Provider tests',
+      'description' => 'Confirm that the default route provider is working correctly.',
       'group' => 'Routing',
     );
   }
@@ -57,11 +57,11 @@ public function tearDown() {
   public function testCandidateOutlines() {
 
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection);
+    $provider = new RouteProvider($connection);
 
     $parts = array('node', '5', 'edit');
 
-    $candidates = $matcher->getCandidateOutlines($parts);
+    $candidates = $provider->getCandidateOutlines($parts);
 
     $candidates = array_flip($candidates);
 
@@ -77,7 +77,7 @@ public function testCandidateOutlines() {
    */
   function testExactPathMatch() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -89,7 +89,7 @@ function testExactPathMatch() {
 
     $request = Request::create($path, 'GET');
 
-    $routes = $matcher->matchRequestPartial($request);
+    $routes = $provider->getRouteCollectionForRequest($request);
 
     foreach ($routes as $route) {
       $this->assertEqual($route->getPattern(), $path, 'Found path has correct pattern');
@@ -101,7 +101,7 @@ function testExactPathMatch() {
    */
   function testOutlinePathMatch() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -113,14 +113,14 @@ function testOutlinePathMatch() {
 
     $request = Request::create($path, 'GET');
 
-    $routes = $matcher->matchRequestPartial($request);
+    $routes = $provider->getRouteCollectionForRequest($request);
 
     // All of the matching paths have the correct pattern.
     foreach ($routes as $route) {
       $this->assertEqual($route->compile()->getPatternOutline(), '/path/%/one', 'Found path has correct pattern');
     }
 
-    $this->assertEqual(count($routes->all()), 2, 'The correct number of routes was found.');
+    $this->assertEqual(count($routes), 2, 'The correct number of routes was found.');
     $this->assertNotNull($routes->get('route_a'), 'The first matching route was found.');
     $this->assertNotNull($routes->get('route_b'), 'The second matching route was not found.');
   }
@@ -130,7 +130,7 @@ function testOutlinePathMatch() {
    */
   function testOutlinePathMatchTrailingSlash() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -142,14 +142,14 @@ function testOutlinePathMatchTrailingSlash() {
 
     $request = Request::create($path, 'GET');
 
-    $routes = $matcher->matchRequestPartial($request);
+    $routes = $provider->getRouteCollectionForRequest($request);
 
     // All of the matching paths have the correct pattern.
     foreach ($routes as $route) {
       $this->assertEqual($route->compile()->getPatternOutline(), '/path/%/one', 'Found path has correct pattern');
     }
 
-    $this->assertEqual(count($routes->all()), 2, 'The correct number of routes was found.');
+    $this->assertEqual(count($routes), 2, 'The correct number of routes was found.');
     $this->assertNotNull($routes->get('route_a'), 'The first matching route was found.');
     $this->assertNotNull($routes->get('route_b'), 'The second matching route was not found.');
   }
@@ -159,7 +159,7 @@ function testOutlinePathMatchTrailingSlash() {
    */
   function testOutlinePathMatchDefaults() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -177,15 +177,14 @@ function testOutlinePathMatchDefaults() {
     $request = Request::create($path, 'GET');
 
     try {
-      $routes = $matcher->matchRequestPartial($request);
+      $routes = $provider->getRouteCollectionForRequest($request);
 
       // All of the matching paths have the correct pattern.
       foreach ($routes as $route) {
-        $compiled = $route->compile();
         $this->assertEqual($route->compile()->getPatternOutline(), '/some/path', 'Found path has correct pattern');
       }
 
-      $this->assertEqual(count($routes->all()), 1, 'The correct number of routes was found.');
+      $this->assertEqual(count($routes), 1, 'The correct number of routes was found.');
       $this->assertNotNull($routes->get('poink'), 'The first matching route was found.');
     }
     catch (ResourceNotFoundException $e) {
@@ -198,7 +197,7 @@ function testOutlinePathMatchDefaults() {
    */
   function testOutlinePathMatchDefaultsCollision() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -217,15 +216,14 @@ function testOutlinePathMatchDefaultsCollision() {
     $request = Request::create($path, 'GET');
 
     try {
-      $routes = $matcher->matchRequestPartial($request);
+      $routes = $provider->getRouteCollectionForRequest($request);
 
       // All of the matching paths have the correct pattern.
       foreach ($routes as $route) {
-        $compiled = $route->compile();
         $this->assertEqual($route->compile()->getPatternOutline(), '/some/path', 'Found path has correct pattern');
       }
 
-      $this->assertEqual(count($routes->all()), 1, 'The correct number of routes was found.');
+      $this->assertEqual(count($routes), 1, 'The correct number of routes was found.');
       $this->assertNotNull($routes->get('poink'), 'The first matching route was found.');
     }
     catch (ResourceNotFoundException $e) {
@@ -238,7 +236,7 @@ function testOutlinePathMatchDefaultsCollision() {
    */
   function testOutlinePathMatchDefaultsCollision2() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -257,14 +255,14 @@ function testOutlinePathMatchDefaultsCollision2() {
     $request = Request::create($path, 'GET');
 
     try {
-      $routes = $matcher->matchRequestPartial($request);
+      $routes = $provider->getRouteCollectionForRequest($request);
 
       // All of the matching paths have the correct pattern.
       foreach ($routes as $route) {
         $this->assertEqual($route->compile()->getPatternOutline(), '/some/path/here', 'Found path has correct pattern');
       }
 
-      $this->assertEqual(count($routes->all()), 1, 'The correct number of routes was found.');
+      $this->assertEqual(count($routes), 1, 'The correct number of routes was found.');
       $this->assertNotNull($routes->get('narf'), 'The first matching route was found.');
     }
     catch (ResourceNotFoundException $e) {
@@ -277,7 +275,7 @@ function testOutlinePathMatchDefaultsCollision2() {
    */
   function testOutlinePathNoMatch() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -290,13 +288,12 @@ function testOutlinePathNoMatch() {
     $request = Request::create($path, 'GET');
 
     try {
-      $routes = $matcher->matchRequestPartial($request);
+      $routes = $provider->getRouteCollectionForRequest($request);
       $this->fail(t('No exception was thrown.'));
     }
     catch (Exception $e) {
       $this->assertTrue($e instanceof ResourceNotFoundException, 'The correct exception was thrown.');
     }
-
   }
 
   /**
@@ -304,7 +301,7 @@ function testOutlinePathNoMatch() {
    */
   function testSystemPathMatch() {
     $connection = Database::getConnection();
-    $matcher = new PathMatcher($connection, 'test_routes');
+    $provider = new RouteProvider($connection, 'test_routes');
 
     $this->fixtures->createTables($connection);
 
@@ -315,7 +312,7 @@ function testSystemPathMatch() {
     $request = Request::create('/path/one', 'GET');
     $request->attributes->set('system_path', 'path/two');
 
-    $routes = $matcher->matchRequestPartial($request);
+    $routes = $provider->getRouteCollectionForRequest($request);
 
     foreach ($routes as $route) {
       $this->assertEqual($route->getPattern(), '/path/two', 'Found path has correct pattern');
diff --git a/core/vendor/autoload.php b/core/vendor/autoload.php
index daa7ee7..7bc9123 100644
--- a/core/vendor/autoload.php
+++ b/core/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer' . '/autoload_real.php';
 
-return ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592::getLoader();
+return ComposerAutoloaderInit23a41d5f637bb8e297fc063ef4ab931a::getLoader();
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index 9072401..ecb4b19 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -16,6 +16,7 @@
     'Symfony\\Component\\EventDispatcher\\' => $vendorDir . '/symfony/event-dispatcher/',
     'Symfony\\Component\\DependencyInjection\\' => $vendorDir . '/symfony/dependency-injection/',
     'Symfony\\Component\\ClassLoader\\' => $vendorDir . '/symfony/class-loader/',
+    'Symfony\\Cmf\\Component\\Routing' => $vendorDir . '/symfony-cmf/routing/',
     'Guzzle\\Stream' => $vendorDir . '/guzzle/stream/',
     'Guzzle\\Parser' => $vendorDir . '/guzzle/parser/',
     'Guzzle\\Http' => $vendorDir . '/guzzle/http/',
diff --git a/core/vendor/composer/autoload_real.php b/core/vendor/composer/autoload_real.php
index dbe463c..9634e0b 100644
--- a/core/vendor/composer/autoload_real.php
+++ b/core/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php generated by Composer
 
-class ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592
+class ComposerAutoloaderInit23a41d5f637bb8e297fc063ef4ab931a
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ public static function getLoader()
             return static::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592', 'loadClassLoader'));
+        spl_autoload_register(array('ComposerAutoloaderInit23a41d5f637bb8e297fc063ef4ab931a', 'loadClassLoader'));
         static::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInit23a41d5f637bb8e297fc063ef4ab931a', 'loadClassLoader'));
 
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json
index aaa926b..9dd2912 100644
--- a/core/vendor/composer/installed.json
+++ b/core/vendor/composer/installed.json
@@ -852,5 +852,56 @@
             "client",
             "Guzzle"
         ]
+    },
+    {
+        "name": "symfony-cmf/routing",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "target-dir": "Symfony/Cmf/Component/Routing",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony-cmf/Routing",
+            "reference": "1.0.0-alpha3"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://github.com/symfony-cmf/Routing/archive/1.0.0-alpha3.zip",
+            "reference": "1.0.0-alpha3",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2",
+            "symfony/routing": ">=2.1,<2.3-dev",
+            "symfony/http-kernel": ">=2.1,<2.3-dev"
+        },
+        "time": "2012-12-16 17:52:57",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0-dev"
+            }
+        },
+        "installation-source": "source",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Cmf\\Component\\Routing": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Symfony CMF Community",
+                "homepage": "https://github.com/symfony-cmf/Routing/contributors"
+            }
+        ],
+        "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers",
+        "homepage": "http://cmf.symfony.com",
+        "keywords": [
+            "database",
+            "routing"
+        ]
     }
 ]
diff --git a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing
new file mode 160000
index 0000000..04da0f0
--- /dev/null
+++ b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing
@@ -0,0 +1 @@
+Subproject commit 04da0f0a8e308e199c52549d1d04b208cc2058db
