diff --git a/autoload.php b/autoload.php
index caedb48..7c5bb25 100644
--- a/autoload.php
+++ b/autoload.php
@@ -1,19 +1,3 @@
 <?php
-
-/**
- * @file
- * Includes the autoloader created by Composer.
- *
- * This file can be edited to change the autoloader if you are managing a
- * project's dependencies using Composer. If Drupal code requires the
- * autoloader, it should always be loaded using this file so that projects
- * using Composer continue to work.
- *
- * @see composer.json
- * @see index.php
- * @see core/install.php
- * @see core/rebuild.php
- * @see core/modules/statistics/statistics.php
- */
-
-return require __DIR__ . '/core/vendor/autoload.php';
+// Generated by composer_manager.
+return require __DIR__ . '/vendor/autoload.php';
diff --git a/composer.json b/composer.json
index 5bec2ee..58cb3b1 100644
--- a/composer.json
+++ b/composer.json
@@ -1,22 +1,166 @@
 {
-  "name": "drupal/drupal",
-  "description": "Drupal is an open source content management platform powering millions of websites and applications.",
-  "type": "project",
-  "license": "GPL-2.0+",
-  "require": {
-    "composer/installers": "^1.0.20",
-    "drupal/core": "~8.0"
-  },
-  "minimum-stability": "dev",
-  "prefer-stable": true,
-  "config": {
-    "preferred-install": "dist",
-    "autoloader-suffix": "Drupal8"
-  },
-  "extra": {
-    "_readme": [
-      "By default Drupal loads the autoloader from ./core/vendor/autoload.php.",
-      "To change the autoloader you can edit ./autoload.php."
-    ]
-  }
-}
+    "name": "drupal/drupal",
+    "type": "project",
+    "license": "GPL-2.0+",
+    "require": {
+        "commercie/currency": "dev-master",
+        "commercie/currency-exchange": "0.4.*",
+        "symfony/class-loader": "2.7.*",
+        "symfony/console": "2.7.*",
+        "symfony/css-selector": "2.7.*",
+        "symfony/dependency-injection": "2.7.*",
+        "symfony/event-dispatcher": "2.7.*",
+        "symfony/http-foundation": "2.7.*",
+        "symfony/http-kernel": "2.7.*",
+        "symfony/routing": "2.7.*",
+        "symfony/serializer": "2.7.*",
+        "symfony/translation": "2.7.*",
+        "symfony/validator": "2.7.*",
+        "symfony/process": "2.7.*",
+        "symfony/yaml": "2.7.*",
+        "twig/twig": "1.20.*",
+        "doctrine/common": "~2.4.2",
+        "doctrine/annotations": "1.2.*",
+        "guzzlehttp/guzzle": "dev-master#1879fbe853b0c64d109e369c7aeff09849e62d1e",
+        "symfony-cmf/routing": "1.3.*",
+        "easyrdf/easyrdf": "0.9.*",
+        "phpunit/phpunit": "4.6.*",
+        "zendframework/zend-feed": "2.4.*",
+        "mikey179/vfsStream": "~1.2",
+        "stack/builder": "1.0.*",
+        "egulias/email-validator": "1.2.*",
+        "behat/mink": "~1.6",
+        "behat/mink-goutte-driver": "dev-master#cc5ce119b5a8e06662f634b35967aff0b0c7dfdd",
+        "fabpot/goutte": "~3.1",
+        "masterminds/html5": "~2.1",
+        "symfony/psr-http-message-bridge": "v0.2",
+        "zendframework/zend-diactoros": "1.1.0",
+        "composer/installers": "^1.0.20"
+    },
+    "require-dev": {
+        "satooshi/php-coveralls": "dev-master"
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "replace": {
+        "drupal/action": "self.version",
+        "drupal/aggregator": "self.version",
+        "drupal/bartik": "self.version",
+        "drupal/ban": "self.version",
+        "drupal/basic_auth": "self.version",
+        "drupal/block": "self.version",
+        "drupal/block_content": "self.version",
+        "drupal/book": "self.version",
+        "drupal/breakpoint": "self.version",
+        "drupal/ckeditor": "self.version",
+        "drupal/classy": "self.version",
+        "drupal/color": "self.version",
+        "drupal/comment": "self.version",
+        "drupal/config": "self.version",
+        "drupal/config_translation": "self.version",
+        "drupal/contact": "self.version",
+        "drupal/content_translation": "self.version",
+        "drupal/contextual": "self.version",
+        "drupal/core-annotation": "self.version",
+        "drupal/core-bridge": "self.version",
+        "drupal/core-datetime": "self.version",
+        "drupal/core-diff": "self.version",
+        "drupal/core-discovery": "self.version",
+        "drupal/core-event-dispatcher": "self.version",
+        "drupal/core-file-cache": "self.version",
+        "drupal/core-gettext": "self.version",
+        "drupal/core-graph": "self.version",
+        "drupal/core-php-storage": "self.version",
+        "drupal/core-plugin": "self.version",
+        "drupal/core-proxy-builder": "self.version",
+        "drupal/core-serialization": "self.version",
+        "drupal/core-transliteration": "self.version",
+        "drupal/core-utility": "self.version",
+        "drupal/core-uuid": "self.version",
+        "drupal/datetime": "self.version",
+        "drupal/dblog": "self.version",
+        "drupal/editor": "self.version",
+        "drupal/entity_reference": "self.version",
+        "drupal/field": "self.version",
+        "drupal/field_ui": "self.version",
+        "drupal/file": "self.version",
+        "drupal/filter": "self.version",
+        "drupal/forum": "self.version",
+        "drupal/hal": "self.version",
+        "drupal/help": "self.version",
+        "drupal/history": "self.version",
+        "drupal/image": "self.version",
+        "drupal/language": "self.version",
+        "drupal/link": "self.version",
+        "drupal/locale": "self.version",
+        "drupal/minimal": "self.version",
+        "drupal/menu_link_content": "self.version",
+        "drupal/menu_ui": "self.version",
+        "drupal/migrate": "self.version",
+        "drupal/migrate_drupal": "self.version",
+        "drupal/node": "self.version",
+        "drupal/options": "self.version",
+        "drupal/page_cache": "self.version",
+        "drupal/path": "self.version",
+        "drupal/quickedit": "self.version",
+        "drupal/rdf": "self.version",
+        "drupal/responsive_image": "self.version",
+        "drupal/rest": "self.version",
+        "drupal/search": "self.version",
+        "drupal/serialization": "self.version",
+        "drupal/seven": "self.version",
+        "drupal/shortcut": "self.version",
+        "drupal/simpletest": "self.version",
+        "drupal/standard": "self.version",
+        "drupal/stark": "self.version",
+        "drupal/statistics": "self.version",
+        "drupal/syslog": "self.version",
+        "drupal/system": "self.version",
+        "drupal/taxonomy": "self.version",
+        "drupal/telephone": "self.version",
+        "drupal/text": "self.version",
+        "drupal/toolbar": "self.version",
+        "drupal/tour": "self.version",
+        "drupal/tracker": "self.version",
+        "drupal/update": "self.version",
+        "drupal/user": "self.version",
+        "drupal/views": "self.version",
+        "drupal/views_ui": "self.version",
+        "drupal/core": "self.version"
+    },
+    "scripts": {
+        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
+        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
+        "post-install-cmd": "Drupal\\composer_manager\\Composer\\Command::rewriteAutoload",
+        "drupal-rebuild": "Drupal\\composer_manager\\Composer\\Command::rebuild",
+        "drupal-install": "Drupal\\composer_manager\\Composer\\Command::install",
+        "drupal-update": "Drupal\\composer_manager\\Composer\\Command::update"
+    },
+    "autoload": {
+        "psr-4": {
+            "Drupal\\Core\\": "core/lib/Drupal/Core",
+            "Drupal\\Component\\": "core/lib/Drupal/Component",
+            "Drupal\\Driver\\": "drivers/lib/Drupal/Driver",
+            "Drupal\\composer_manager\\Composer\\": "modules/composer_manager/src/Composer"
+        },
+        "files": [
+            "core/lib/Drupal.php"
+        ],
+        "classmap": [
+            "core/lib/Drupal/Component/Utility/Timer.php",
+            "core/lib/Drupal/Component/Utility/Unicode.php",
+            "core/lib/Drupal/Core/Database/Database.php",
+            "core/lib/Drupal/Core/DrupalKernel.php",
+            "core/lib/Drupal/Core/DrupalKernelInterface.php",
+            "core/lib/Drupal/Core/Site/Settings.php"
+        ]
+    },
+    "config": {
+        "preferred-install": "dist",
+        "autoloader-suffix": "Drupal8"
+    },
+    "extra": {
+        "_generator": "Generated by composer_manager",
+        "_sources": "drupal/core, drupal/currency, drupal/payment, drupal/plugin"
+    }
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Component/Plugin/Definition/PluginDefinitionInterface.php b/core/lib/Drupal/Component/Plugin/Definition/PluginDefinitionInterface.php
new file mode 100644
index 0000000..60e6066
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Definition/PluginDefinitionInterface.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\PluginDefinitionInterface.
+ */
+
+namespace Drupal\Component\Plugin\Definition;
+
+/**
+ * Defines a plugin definition.
+ *
+ * Object-based plugin definitions MUST implement this interface.
+ *
+ * @ingroup Plugin
+ */
+interface PluginDefinitionInterface {
+
+  /**
+   * Sets the class.
+   *
+   * @param string $class
+   *   A fully qualified class name.
+   *
+   * @return $this
+   *
+   * @throws \InvalidArgumentException
+   *   If the class is invalid.
+   */
+  public function setClass($class);
+
+  /**
+   * Gets the class.
+   *
+   * @return string
+   *   A fully qualified class name.
+   */
+  public function getClass();
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
index 1902b56..46c200d 100644
--- a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
+++ b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
@@ -6,6 +6,7 @@
 
 namespace Drupal\Component\Plugin\Factory;
 
+use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Component\Plugin\Exception\PluginException;
 
@@ -63,7 +64,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
    *
    * @param string $plugin_id
    *   The id of a plugin.
-   * @param mixed $plugin_definition
+   * @param \Drupal\Component\Plugin\Definition\PluginDefinitionInterface|mixed[] $plugin_definition
    *   The plugin definition associated with the plugin ID.
    * @param string $required_interface
    *   (optional) THe required plugin interface.
@@ -77,18 +78,32 @@ public function createInstance($plugin_id, array $configuration = array()) {
    *
    */
   public static function getPluginClass($plugin_id, $plugin_definition = NULL, $required_interface = NULL) {
-    if (empty($plugin_definition['class'])) {
-      throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id));
+    $missing_class_message = sprintf('The plugin (%s) did not specify an instance class.', $plugin_id);
+    if (is_array($plugin_definition)) {
+      if (empty($plugin_definition['class'])) {
+        throw new PluginException($missing_class_message);
+      }
+
+      $class = $plugin_definition['class'];
     }
+    elseif ($plugin_definition instanceof PluginDefinitionInterface) {
+      if (!$plugin_definition->getClass()) {
+        throw new PluginException($missing_class_message);
+      }
 
-    $class = $plugin_definition['class'];
+      $class = $plugin_definition->getClass();
+    }
+    else {
+      $plugin_definition_type = is_object($plugin_definition) ? get_class($plugin_definition) : gettype($plugin_definition);
+      throw new PluginException(sprintf('% can only handle plugin definitions that are arrays or that implement %s, but %s given.', __CLASS__, PluginDefinitionInterface::class, $plugin_definition_type));
+    }
 
     if (!class_exists($class)) {
       throw new PluginException(sprintf('Plugin (%s) instance class "%s" does not exist.', $plugin_id, $class));
     }
 
-    if ($required_interface && !is_subclass_of($plugin_definition['class'], $required_interface)) {
-      throw new PluginException(sprintf('Plugin "%s" (%s) must implement interface %s.', $plugin_id, $plugin_definition['class'], $required_interface));
+    if ($required_interface && !is_subclass_of($class, $required_interface)) {
+      throw new PluginException(sprintf('Plugin "%s" (%s) must implement interface %s.', $plugin_id, $class, $required_interface));
     }
 
     return $class;
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index 1a3805e..68dfb30 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\Entity;
+use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
 
 /**
  * Provides an interface for an entity type and its metadata.
@@ -15,7 +16,7 @@
  * implemented to alter existing data and fill-in defaults. Module-specific
  * properties should be documented in the hook implementations defining them.
  */
-interface EntityTypeInterface {
+interface EntityTypeInterface extends PluginDefinitionInterface {
 
   /**
    * The maximum length of ID, in characters.
@@ -67,14 +68,6 @@ public function id();
   public function getProvider();
 
   /**
-   * Gets the name of the entity type class.
-   *
-   * @return string
-   *   The name of the entity type class.
-   */
-  public function getClass();
-
-  /**
    * Gets the name of the original entity type class.
    *
    * In case the class name was changed with setClass(), this will return
@@ -171,16 +164,6 @@ public function isRenderCacheable();
   public function isPersistentlyCacheable();
 
   /**
-   * Sets the name of the entity type class.
-   *
-   * @param string $class
-   *   The name of the entity type class.
-   *
-   * @return $this
-   */
-  public function setClass($class);
-
-  /**
    * Determines if there is a handler for a given type.
    *
    * @param string $handler_type
diff --git a/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php b/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php
index a23b690..d02deee 100644
--- a/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php
+++ b/core/tests/Drupal/Tests/Component/Plugin/DefaultFactoryTest.php
@@ -7,7 +7,11 @@
 
 namespace Drupal\Tests\Component\Plugin;
 
+use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry;
+use Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface;
+use Drupal\plugin_test\Plugin\plugin_test\fruit\Kale;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -17,41 +21,110 @@
 class DefaultFactoryTest extends UnitTestCase {
 
   /**
-   * Tests getPluginClass() with a valid plugin.
+   * Tests getPluginClass() with a valid array plugin definition.
+   *
+   * @covers ::getPluginClass
    */
-  public function testGetPluginClassWithValidPlugin() {
-    $plugin_class = 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry';
+  public function testGetPluginClassWithValidArrayPluginDefinition() {
+    $plugin_class = Cherry::class;
     $class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class]);
 
     $this->assertEquals($plugin_class, $class);
   }
 
   /**
+   * Tests getPluginClass() with a valid object plugin definition.
+   *
+   * @covers ::getPluginClass
+   */
+  public function testGetPluginClassWithValidObjectPluginDefinition() {
+    $plugin_class = Cherry::class;
+    $plugin_definition = $this->getMock(PluginDefinitionInterface::class);
+    $plugin_definition->expects($this->atLeastOnce())
+      ->method('getClass')
+      ->willReturn($plugin_class);
+    $class = DefaultFactory::getPluginClass('cherry', $plugin_definition);
+
+    $this->assertEquals($plugin_class, $class);
+  }
+
+  /**
    * Tests getPluginClass() with a missing class definition.
    *
+   * @covers ::getPluginClass
+   *
    * @expectedException \Drupal\Component\Plugin\Exception\PluginException
    * @expectedExceptionMessage The plugin (cherry) did not specify an instance class.
    */
-  public function testGetPluginClassWithMissingClass() {
+  public function testGetPluginClassWithMissingClassWithArrayPluginDefinition() {
     DefaultFactory::getPluginClass('cherry', []);
   }
 
   /**
+   * Tests getPluginClass() with a missing class definition.
+   *
+   * @covers ::getPluginClass
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\PluginException
+   * @expectedExceptionMessage The plugin (cherry) did not specify an instance class.
+   */
+  public function testGetPluginClassWithMissingClassWithObjectPluginDefinition() {
+    $plugin_definition = $this->getMock(PluginDefinitionInterface::class);
+    DefaultFactory::getPluginClass('cherry', $plugin_definition);
+  }
+
+  /**
    * Tests getPluginClass() with a not existing class definition.
    *
+   * @covers ::getPluginClass
+   *
    * @expectedException \Drupal\Component\Plugin\Exception\PluginException
    * @expectedExceptionMessage Plugin (kiwifruit) instance class "\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit" does not exist.
    */
-  public function testGetPluginClassWithNotExistingClass() {
+  public function testGetPluginClassWithNotExistingClassWithArrayPluginDefinition() {
     DefaultFactory::getPluginClass('kiwifruit', ['class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit']);
   }
 
   /**
+   * Tests getPluginClass() with a not existing class definition.
+   *
+   * @covers ::getPluginClass
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\PluginException
+   */
+  public function testGetPluginClassWithNotExistingClassWithObjectPluginDefinition() {
+    $plugin_class = '\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit';
+    $plugin_definition = $this->getMock(PluginDefinitionInterface::class);
+    $plugin_definition->expects($this->atLeastOnce())
+      ->method('getClass')
+      ->willReturn($plugin_class);
+    DefaultFactory::getPluginClass('kiwifruit', $plugin_definition);
+  }
+
+  /**
+   * Tests getPluginClass() with a required interface.
+   *
+   * @covers ::getPluginClass
+   */
+  public function testGetPluginClassWithInterfaceWithArrayPluginDefinition() {
+    $plugin_class = Cherry::class;
+    $class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class], FruitInterface::class);
+
+    $this->assertEquals($plugin_class, $class);
+  }
+
+  /**
    * Tests getPluginClass() with a required interface.
+   *
+   * @covers ::getPluginClass
    */
-  public function testGetPluginClassWithInterface() {
-    $plugin_class = 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry';
-    $class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class], '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
+  public function testGetPluginClassWithInterfaceWithObjectPluginDefinition() {
+    $plugin_class = Cherry::class;
+    $plugin_definition = $this->getMock(PluginDefinitionInterface::class);
+    $plugin_definition->expects($this->atLeastOnce())
+      ->method('getClass')
+      ->willReturn($plugin_class);
+    $class = DefaultFactory::getPluginClass('cherry', $plugin_definition, FruitInterface::class);
 
     $this->assertEquals($plugin_class, $class);
   }
@@ -59,12 +132,30 @@ public function testGetPluginClassWithInterface() {
   /**
    * Tests getPluginClass() with a required interface but no implementation.
    *
+   * @covers ::getPluginClass
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\PluginException
+   * @expectedExceptionMessage Plugin "cherry" (Drupal\plugin_test\Plugin\plugin_test\fruit\Kale) must implement interface Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface.
+   */
+  public function testGetPluginClassWithInterfaceAndInvalidClassWithArrayPluginDefinition() {
+    $plugin_class = Kale::class;
+    DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class, 'provider' => 'core'], FruitInterface::class);
+  }
+
+  /**
+   * Tests getPluginClass() with a required interface but no implementation.
+   *
+   * @covers ::getPluginClass
+   *
    * @expectedException \Drupal\Component\Plugin\Exception\PluginException
-   * @expectedExceptionMessage Plugin "cherry" (Drupal\plugin_test\Plugin\plugin_test\fruit\Kale) must implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface.
    */
-  public function testGetPluginClassWithInterfaceAndInvalidClass() {
-    $plugin_class = 'Drupal\plugin_test\Plugin\plugin_test\fruit\Kale';
-    DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class, 'provider' => 'core'], '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
+  public function testGetPluginClassWithInterfaceAndInvalidClassWithObjectPluginDefinition() {
+    $plugin_class = Kale::class;
+    $plugin_definition = $this->getMock(PluginDefinitionInterface::class);
+    $plugin_definition->expects($this->atLeastOnce())
+      ->method('getClass')
+      ->willReturn($plugin_class);
+    DefaultFactory::getPluginClass('cherry', $plugin_definition, FruitInterface::class);
   }
 
 }
