diff --git a/app/code/Magento/Backend/App/BackendAppList.php b/app/code/Magento/Backend/App/BackendAppList.php
index 224ce9893100c6b416da0362ca9a0e3af569bf1e..afb812b823488b29898a2027afa87b6980d9974c 100644
--- a/app/code/Magento/Backend/App/BackendAppList.php
+++ b/app/code/Magento/Backend/App/BackendAppList.php
@@ -44,6 +44,7 @@ class BackendAppList
         if ($appName && isset($this->backendApps[$appName])) {
             return $this->backendApps[$appName];
         }
+        return null;
     }
 
     /**
diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php
index 0013ba1f17f1bb404640c5da4b3f8ddb2d77d632..86ed5c6a10766bb8a3f475e9b2bf70e0d4c9e279 100644
--- a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php
+++ b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php
@@ -59,33 +59,27 @@ class Stock extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\
             "bo.parent_id = product.$linkField",
             []
         );
-        $this->_addWebsiteJoinToSelect($select, false);
         $status = new \Zend_Db_Expr(
             'MAX(' . $connection->getCheckSql('e.required_options = 0', 'i.stock_status', '0') . ')'
         );
-        $select->columns(
-            'website_id',
-            'cw'
-        )->join(
+        $select->join(
             ['cis' => $this->getTable('cataloginventory_stock')],
             '',
-            ['stock_id']
+            ['website_id', 'stock_id']
         )->joinLeft(
             ['bs' => $this->getTable('catalog_product_bundle_selection')],
             'bs.option_id = bo.option_id',
             []
         )->joinLeft(
             ['i' => $idxTable],
-            'i.product_id = bs.product_id AND i.website_id = cw.website_id AND i.stock_id = cis.stock_id',
+            'i.product_id = bs.product_id AND i.website_id = cis.website_id AND i.stock_id = cis.stock_id',
             []
         )->joinLeft(
             ['e' => $this->getTable('catalog_product_entity')],
             'e.entity_id = bs.product_id',
             []
-        )->where(
-            'cw.website_id != 0'
         )->group(
-            ['product.entity_id', 'cw.website_id', 'cis.stock_id', 'bo.option_id']
+            ['product.entity_id', 'cis.website_id', 'cis.stock_id', 'bo.option_id']
         )->columns(
             ['option_id' => 'bo.option_id', 'status' => $status]
         );
@@ -118,45 +112,19 @@ class Stock extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\
     protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false)
     {
         $this->_prepareBundleOptionStockData($entityIds, $usePrimaryTable);
-        $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
         $connection = $this->getConnection();
-        $select = $connection->select()->from(
-            ['e' => $this->getTable('catalog_product_entity')],
-            ['entity_id']
-        );
-        $this->_addWebsiteJoinToSelect($select, true);
-        $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id');
-        $select->columns(
-            'cw.website_id'
-        )->join(
-            ['cis' => $this->getTable('cataloginventory_stock')],
-            '',
-            ['stock_id']
-        )->joinLeft(
-            ['cisi' => $this->getTable('cataloginventory_stock_item')],
-            'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id',
-            []
+        $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable);
+        $select->reset(
+            \Magento\Framework\DB\Select::COLUMNS
+        )->columns(
+            ['e.entity_id', 'cis.website_id', 'cis.stock_id']
         )->joinLeft(
             ['o' => $this->_getBundleOptionTable()],
-            'o.entity_id = e.entity_id AND o.website_id = cw.website_id AND o.stock_id = cis.stock_id',
+            'o.entity_id = e.entity_id AND o.website_id = cis.website_id AND o.stock_id = cis.stock_id',
             []
         )->columns(
             ['qty' => new \Zend_Db_Expr('0')]
-        )->where(
-            'cw.website_id != 0'
-        )->where(
-            'e.type_id = ?',
-            $this->getTypeId()
-        )->group(
-            ['e.entity_id', 'cw.website_id', 'cis.stock_id']
-        );
-
-        // add limitation of status
-        $condition = $connection->quoteInto(
-            '=?',
-            \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
         );
-        $this->_addAttributeToSelect($select, 'status', "e.$linkField", 'cs.store_id', $condition);
 
         $statusExpr = $this->getStatusExpression($connection);
         $select->columns(
diff --git a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php
similarity index 74%
rename from app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php
rename to app/code/Magento/Catalog/Plugin/Block/Topmenu.php
index 608c7ee74b7cdda6409432f968734f2d1171a088..098b3282a1b107e56703ee4889f9ce005f25d223 100644
--- a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php
+++ b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php
@@ -3,17 +3,16 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-namespace Magento\Catalog\Observer;
+namespace Magento\Catalog\Plugin\Block;
 
 use Magento\Catalog\Model\Category;
 use Magento\Framework\Data\Collection;
 use Magento\Framework\Data\Tree\Node;
-use Magento\Framework\Event\ObserverInterface;
 
 /**
- * Observer that add Categories Tree to Topmenu
+ * Plugin for top menu block
  */
-class AddCatalogToTopmenuItemsObserver implements ObserverInterface
+class Topmenu
 {
     /**
      * Catalog category
@@ -38,11 +37,11 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
     private $layerResolver;
 
     /**
+     * Initialize dependencies.
+     *
      * @param \Magento\Catalog\Helper\Category $catalogCategory
-     * @param \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState
      * @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
-     * @param \Magento\Catalog\Helper\Category $catalogCategory
      * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver
      */
     public function __construct(
@@ -58,26 +57,27 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
     }
 
     /**
-     * Checking whether the using static urls in WYSIWYG allowed event
+     * Build category tree for menu block.
      *
-     * @param \Magento\Framework\Event\Observer $observer
+     * @param \Magento\Theme\Block\Html\Topmenu $subject
+     * @param string $outermostClass
+     * @param string $childrenWrapClass
+     * @param int $limit
      * @return void
+     * @SuppressWarnings("PMD.UnusedFormalParameter")
      */
-    public function execute(\Magento\Framework\Event\Observer $observer)
-    {
-        $block = $observer->getEvent()->getBlock();
-        $menuRootNode = $observer->getEvent()->getMenu();
-        $block->addIdentity(Category::CACHE_TAG);
-
+    public function beforeGetHtml(
+        \Magento\Theme\Block\Html\Topmenu $subject,
+        $outermostClass = '',
+        $childrenWrapClass = '',
+        $limit = 0
+    ) {
         $rootId = $this->storeManager->getStore()->getRootCategoryId();
         $storeId = $this->storeManager->getStore()->getId();
-
         /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
         $collection = $this->getCategoryTree($storeId, $rootId);
-
         $currentCategory = $this->getCurrentCategory();
-
-        $mapping = [$rootId => $menuRootNode];  // use nodes stack to avoid recursion
+        $mapping = [$rootId => $subject->getMenu()];  // use nodes stack to avoid recursion
         foreach ($collection as $category) {
             if (!isset($mapping[$category->getParentId()])) {
                 continue;
@@ -94,8 +94,28 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
             $parentCategoryNode->addChild($categoryNode);
 
             $mapping[$category->getId()] = $categoryNode; //add node in stack
+        }
+    }
 
-            $block->addIdentity(Category::CACHE_TAG . '_' . $category->getId());
+    /**
+     * Add list of associated identities to the top menu block for caching purposes.
+     *
+     * @param \Magento\Theme\Block\Html\Topmenu $subject
+     * @return void
+     */
+    public function beforeGetIdentities(\Magento\Theme\Block\Html\Topmenu $subject)
+    {
+        $subject->addIdentity(Category::CACHE_TAG);
+        $rootId = $this->storeManager->getStore()->getRootCategoryId();
+        $storeId = $this->storeManager->getStore()->getId();
+        /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
+        $collection = $this->getCategoryTree($storeId, $rootId);
+        $mapping = [$rootId => $subject->getMenu()];  // use nodes stack to avoid recursion
+        foreach ($collection as $category) {
+            if (!isset($mapping[$category->getParentId()])) {
+                continue;
+            }
+            $subject->addIdentity(Category::CACHE_TAG . '_' . $category->getId());
         }
     }
 
diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
similarity index 81%
rename from app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php
rename to app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
index 393cf8223d2a2d40ed54802515cdc91fa5fc804a..e0fe2deb232f68b989abb72463268d531e5e81cd 100644
--- a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
@@ -6,16 +6,16 @@
 
 // @codingStandardsIgnoreFile
 
-namespace Magento\Catalog\Test\Unit\Observer;
+namespace Magento\Catalog\Test\Unit\Plugin\Block;
 
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
 
-class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
+class TopmenuTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver
+     * @var \Magento\Catalog\Plugin\Block\Topmenu
      */
-    protected $_observer;
+    protected $block;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Helper\Category
@@ -100,8 +100,8 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
         $collection->expects($this->once())->method('getIterator')
             ->willReturn(new \ArrayIterator([]));
 
-        $this->_observer = (new ObjectManager($this))->getObject(
-            'Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver',
+        $this->block = (new ObjectManager($this))->getObject(
+            \Magento\Catalog\Plugin\Block\Topmenu::class,
             [
                 'catalogCategory' => $this->_catalogCategory,
                 'menuCategoryData' => $this->menuCategoryData,
@@ -142,23 +142,11 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase
         );
 
         $blockMock = $this->_getCleanMock('\Magento\Theme\Block\Html\Topmenu');
-
-        $eventMock = $this->getMock('\Magento\Framework\Event', ['getBlock'], [], '', false);
-        $eventMock->expects($this->once())
-            ->method('getBlock')
-            ->will($this->returnValue($blockMock));
-
-        $observerMock = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent', 'getMenu'], [], '', false);
-        $observerMock->expects($this->any())
-            ->method('getEvent')
-            ->will($this->returnValue($eventMock));
-
-        return $observerMock;
+        return $blockMock;
     }
 
     public function testAddCatalogToTopMenuItems()
     {
-        $observer = $this->_preparationData();
-        $this->_observer->execute($observer);
+        $this->block->beforeGetHtml($this->_preparationData());
     }
 }
diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml
index 19a4f22a3c8e9425d474873f321f08baf062113c..78e46f0c39205ee7172c890739fa60a23946affa 100644
--- a/app/code/Magento/Catalog/etc/di.xml
+++ b/app/code/Magento/Catalog/etc/di.xml
@@ -46,6 +46,9 @@
     <type name="Magento\Customer\Model\ResourceModel\Visitor">
         <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" />
     </type>
+    <type name="Magento\Theme\Block\Html\Topmenu">
+        <plugin name="catalogTopmenu" type="Magento\Catalog\Plugin\Block\Topmenu" />
+    </type>
     <type name="Magento\Framework\Mview\View\StateInterface">
         <plugin name="setStatusForMview" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\MviewState" />
     </type>
diff --git a/app/code/Magento/Catalog/etc/frontend/events.xml b/app/code/Magento/Catalog/etc/frontend/events.xml
index afb3c70a14ade23fc8caab37ab4f3b564ae1f917..5ef8c724683141c38d735fcd0e321615d562ce6a 100644
--- a/app/code/Magento/Catalog/etc/frontend/events.xml
+++ b/app/code/Magento/Catalog/etc/frontend/events.xml
@@ -12,7 +12,4 @@
     <event name="customer_logout">
         <observer name="catalog" instance="Magento\Catalog\Observer\Compare\BindCustomerLogoutObserver" shared="false" />
     </event>
-    <event name="page_block_html_topmenu_gethtml_before">
-        <observer name="catalog_add_topmenu_items" instance="Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver" />
-    </event>
 </config>
diff --git a/app/code/Magento/CatalogInventory/Helper/Stock.php b/app/code/Magento/CatalogInventory/Helper/Stock.php
index 599b2d44e2ae38e45e7477a5c45edb426e0a164b..13e311d1fe5aeb4af1282edcf29215fe67570199 100644
--- a/app/code/Magento/CatalogInventory/Helper/Stock.php
+++ b/app/code/Magento/CatalogInventory/Helper/Stock.php
@@ -12,9 +12,11 @@ use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory;
 use Magento\CatalogInventory\Model\ResourceModel\Stock\Status;
 use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection;
 use Magento\Catalog\Model\Product;
+use Magento\CatalogInventory\Api\StockConfigurationInterface;
 
 /**
  * Class Stock
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class Stock
 {
@@ -47,6 +49,11 @@ class Stock
      */
     private $stockRegistryProvider;
 
+    /**
+     * @var StockConfigurationInterface
+     */
+    private $stockConfiguration;
+
     /**
      * @param StoreManagerInterface $storeManager
      * @param ScopeConfigInterface $scopeConfig
@@ -75,7 +82,7 @@ class Stock
     public function assignStatusToProduct(Product $product, $status = null)
     {
         if ($status === null) {
-            $websiteId = $product->getStore()->getWebsiteId();
+            $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
             $stockStatus = $this->stockRegistryProvider->getStockStatus($product->getId(), $websiteId);
             $status = $stockStatus->getStockStatus();
         }
@@ -90,7 +97,7 @@ class Stock
      */
     public function addStockStatusToProducts(AbstractCollection $productCollection)
     {
-        $websiteId = $this->storeManager->getStore($productCollection->getStoreId())->getWebsiteId();
+        $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
         foreach ($productCollection as $product) {
             $productId = $product->getId();
             $stockStatus = $this->stockRegistryProvider->getStockStatus($productId, $websiteId);
@@ -161,4 +168,18 @@ class Stock
         }
         return $this->stockStatusResource;
     }
+
+    /**
+     * @return StockConfigurationInterface
+     *
+     * @deprecated
+     */
+    private function getStockConfiguration()
+    {
+        if ($this->stockConfiguration === null) {
+            $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get('Magento\CatalogInventory\Api\StockConfigurationInterface');
+        }
+        return $this->stockConfiguration;
+    }
 }
diff --git a/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php b/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php
index db78c8e17322bd12129cc488248cd0703bb83781..1915a576939ac0aca869e5072abb3e828820dea6 100644
--- a/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php
+++ b/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php
@@ -25,7 +25,6 @@ class Backorders extends AbstractValue
                 || $this->getValue() == \Magento\CatalogInventory\Model\Stock::BACKORDERS_NO
             )
         ) {
-            $this->stockIndex->rebuild();
             $this->_stockIndexerProcessor->markIndexerAsInvalid();
         }
         return parent::afterSave();
diff --git a/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php b/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php
index 559e6235951dbae06698ce2def0eccbbd5dfd915..6edab6f3d4eb629e2947676c21d07fe827d52cdd 100644
--- a/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php
+++ b/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php
@@ -20,7 +20,6 @@ class Managestock extends AbstractValue
     public function afterSave()
     {
         if ($this->isValueChanged()) {
-            $this->stockIndex->rebuild();
             $this->_stockIndexerProcessor->markIndexerAsInvalid();
         }
         return parent::afterSave();
diff --git a/app/code/Magento/CatalogInventory/Model/Configuration.php b/app/code/Magento/CatalogInventory/Model/Configuration.php
index 445057c4c08d8174768a9237359bdb4f830066cd..d1509eec3d4adce87cfd4b8ecf75f63485bbeff5 100644
--- a/app/code/Magento/CatalogInventory/Model/Configuration.php
+++ b/app/code/Magento/CatalogInventory/Model/Configuration.php
@@ -148,7 +148,9 @@ class Configuration implements StockConfigurationInterface
      */
     public function getDefaultScopeId()
     {
-        return (int) $this->storeManager->getWebsite()->getId();
+        // TODO: should be fixed in MAGETWO-46043
+        // "0" is id of admin website, which is used in backend during save entity
+        return 0;
     }
 
     /**
diff --git a/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php
index 82e9e1b1c94c607103230917753f0aa1c5afaede..df910254082185145212c325568a971a75a9bd85 100644
--- a/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php
+++ b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php
@@ -24,6 +24,7 @@ class AroundProductRepositorySave
 
     /**
      * @var StoreManagerInterface
+     * @deprecated
      */
     protected $storeManager;
 
@@ -80,7 +81,7 @@ class AroundProductRepositorySave
 
         // set fields that the customer should not care about
         $stockItem->setProductId($product->getId());
-        $stockItem->setWebsiteId($this->storeManager->getStore($product->getStoreId())->getWebsiteId());
+        $stockItem->setWebsiteId($this->stockConfiguration->getDefaultScopeId());
 
         $this->stockRegistry->updateStockItemBySku($product->getSku(), $stockItem);
 
diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
index 3bb9ef4c4d5c6f847d17365df179f54b0b678752..40245db2f3372234ad18a988140195e88a11b971 100644
--- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
+++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
@@ -9,6 +9,7 @@ namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock;
 use Magento\Catalog\Model\ResourceModel\Product\Indexer\AbstractIndexer;
 use Magento\CatalogInventory\Model\Stock;
 use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\CatalogInventory\Api\StockConfigurationInterface;
 
 /**
  * CatalogInventory Default Stock Status Indexer Resource Model
@@ -42,6 +43,11 @@ class DefaultStock extends AbstractIndexer implements StockInterface
      */
     private $queryProcessorComposite;
 
+    /**
+     * @var StockConfigurationInterface
+     */
+    protected $stockConfiguration;
+
     /**
      * Class constructor
      *
@@ -176,43 +182,29 @@ class DefaultStock extends AbstractIndexer implements StockInterface
      */
     protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false)
     {
-        $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
         $connection = $this->getConnection();
         $qtyExpr = $connection->getCheckSql('cisi.qty > 0', 'cisi.qty', 0);
         $select = $connection->select()->from(
             ['e' => $this->getTable('catalog_product_entity')],
             ['entity_id']
         );
-        $this->_addWebsiteJoinToSelect($select, true);
-        $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id');
-        $select->columns('cw.website_id')->join(
+        $select->join(
             ['cis' => $this->getTable('cataloginventory_stock')],
             '',
-            ['stock_id']
-        )->joinLeft(
+            ['website_id', 'stock_id']
+        )->joinInner(
             ['cisi' => $this->getTable('cataloginventory_stock_item')],
             'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id',
             []
-        )->columns(['qty' => new \Zend_Db_Expr('SUM(' . $qtyExpr . ')')])
-            ->where('cw.website_id != 0')
-            ->where('e.type_id = ?', $this->getTypeId())
-            ->group(['e.entity_id', 'cw.website_id']);
-
-        // add limitation of status
-        $condition = $connection->quoteInto(
-            '=?',
-            \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
-        );
-        $this->_addAttributeToSelect(
-            $select,
-            'status',
-            'e.' . $metadata->getLinkField(),
-            'cs.store_id',
-            $condition
-        );
+        )->columns(
+            ['qty' => $qtyExpr]
+        )->where(
+            'cis.website_id = ?',
+            $this->getStockConfiguration()->getDefaultScopeId()
+        )->where('e.type_id = ?', $this->getTypeId())
+            ->group(['e.entity_id', 'cis.website_id', 'cis.stock_id']);
 
         $select->columns(['status' => $this->getStatusExpression($connection, true)]);
-
         if ($entityIds !== null) {
             $select->where('e.entity_id IN(?)', $entityIds);
         }
@@ -325,6 +317,20 @@ class DefaultStock extends AbstractIndexer implements StockInterface
         return $statusExpr;
     }
 
+    /**
+     * @return StockConfigurationInterface
+     *
+     * @deprecated
+     */
+    protected function getStockConfiguration()
+    {
+        if ($this->stockConfiguration === null) {
+            $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get('Magento\CatalogInventory\Api\StockConfigurationInterface');
+        }
+        return $this->stockConfiguration;
+    }
+
     /**
      * @return QueryProcessorComposite
      */
diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php
index f4877e6a3de68fd72a6550d1b6bf6c5b611593bb..17a3e0c9a99494de5efdb4f6825c33fae9e41e54 100644
--- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php
+++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php
@@ -75,6 +75,7 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
 
     /**
      * @var StoreManagerInterface
+     * @deprecated
      */
     protected $storeManager;
 
@@ -189,11 +190,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
      * Set items out of stock basing on their quantities and config settings
      *
      * @param string|int $website
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @return void
      */
     public function updateSetOutOfStock($website = null)
     {
-        $websiteId = $this->storeManager->getWebsite($website)->getId();
+        $websiteId = $this->stockConfiguration->getDefaultScopeId();
         $this->_initConfig();
         $connection = $this->getConnection();
         $values = ['is_in_stock' => 0, 'stock_status_changed_auto' => 1];
@@ -223,11 +225,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
      * Set items in stock basing on their quantities and config settings
      *
      * @param int|string $website
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @return void
      */
     public function updateSetInStock($website)
     {
-        $websiteId = $this->storeManager->getWebsite($website)->getId();
+        $websiteId = $this->stockConfiguration->getDefaultScopeId();
         $this->_initConfig();
         $connection = $this->getConnection();
         $values = ['is_in_stock' => 1];
@@ -255,11 +258,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme
      * Update items low stock date basing on their quantities and config settings
      *
      * @param int|string $website
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @return void
      */
     public function updateLowStockDate($website)
     {
-        $websiteId = $this->storeManager->getWebsite($website)->getId();
+        $websiteId = $this->stockConfiguration->getDefaultScopeId();
         $this->_initConfig();
 
         $connection = $this->getConnection();
diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php
index d08bd31df9eeb517f3577ce3aff34de85c42479f..32d21f388f03e30510dfb1179fdf335654b4c0a4 100644
--- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php
+++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php
@@ -57,13 +57,13 @@ class Item extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      *
      * @param \Magento\CatalogInventory\Api\Data\StockItemInterface $item
      * @param int $productId
-     * @param int $websiteId
+     * @param int $stockId
      * @return $this
      */
-    public function loadByProductId(\Magento\CatalogInventory\Api\Data\StockItemInterface $item, $productId, $websiteId)
+    public function loadByProductId(\Magento\CatalogInventory\Api\Data\StockItemInterface $item, $productId, $stockId)
     {
-        $select = $this->_getLoadSelect('product_id', $productId, $item)->where('website_id = :website_id');
-        $data = $this->getConnection()->fetchRow($select, [':website_id' => $websiteId]);
+        $select = $this->_getLoadSelect('product_id', $productId, $item)->where('stock_id = :stock_id');
+        $data = $this->getConnection()->fetchRow($select, [':stock_id' => $stockId]);
         if ($data) {
             $item->setData($data);
         } else {
diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php
index 551f5e0c3b8fffd04eaac0e5c18bd1a1977990d6..d1e038071ecc52a7adf9f5452076e95cd06358e5 100644
--- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php
+++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php
@@ -13,6 +13,7 @@ use Magento\Framework\Data\ObjectFactory;
 use Magento\Store\Model\StoreManagerInterface;
 use Psr\Log\LoggerInterface as Logger;
 use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
+use Magento\CatalogInventory\Api\StockConfigurationInterface;
 
 /**
  * Interface StockItemCriteriaMapper
@@ -20,6 +21,17 @@ use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
  */
 class StockItemCriteriaMapper extends GenericMapper
 {
+    /**
+     * @var StockConfigurationInterface
+     */
+    private $stockConfiguration;
+
+    /**
+     * @var StoreManagerInterface
+     * @deprecated
+     */
+    private $storeManager;
+
     /**
      * @param Logger $logger
      * @param FetchStrategyInterface $fetchStrategy
@@ -107,10 +119,11 @@ class StockItemCriteriaMapper extends GenericMapper
 
     /**
      * @inheritdoc
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function mapStockStatus($storeId = null)
     {
-        $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId();
+        $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
         $this->getSelect()->joinLeft(
             ['status_table' => $this->getTable('cataloginventory_stock_status')],
             'main_table.product_id=status_table.product_id' .
@@ -149,4 +162,18 @@ class StockItemCriteriaMapper extends GenericMapper
         }
         $this->addFieldToFilter('main_table.qty', [$methods[$comparisonMethod] => $qty]);
     }
+
+    /**
+     * @return StockConfigurationInterface
+     *
+     * @deprecated
+     */
+    private function getStockConfiguration()
+    {
+        if ($this->stockConfiguration === null) {
+            $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get('Magento\CatalogInventory\Api\StockConfigurationInterface');
+        }
+        return $this->stockConfiguration;
+    }
 }
diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php
index 75b325458ccaa2c9c4bfb3c0c16ffc381c7cab90..f7410de156fb42e4549b3d1910d5c5d9d5fb0d27 100644
--- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php
+++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php
@@ -6,9 +6,11 @@
 namespace Magento\CatalogInventory\Model\ResourceModel\Stock;
 
 use Magento\CatalogInventory\Model\Stock;
+use Magento\CatalogInventory\Api\StockConfigurationInterface;
 
 /**
  * CatalogInventory Stock Status per website Resource Model
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
 {
@@ -16,6 +18,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      * Store model manager
      *
      * @var \Magento\Store\Model\StoreManagerInterface
+     * @deprecated
      */
     protected $_storeManager;
 
@@ -31,6 +34,11 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      */
     protected $eavConfig;
 
+    /**
+     * @var StockConfigurationInterface
+     */
+    private $stockConfiguration;
+
     /**
      * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -190,11 +198,12 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      *
      * @param \Magento\Framework\DB\Select $select
      * @param \Magento\Store\Model\Website $website
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      * @return Status
      */
     public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Magento\Store\Model\Website $website)
     {
-        $websiteId = $website->getId();
+        $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
         $select->joinLeft(
             ['stock_status' => $this->getMainTable()],
             'e.entity_id = stock_status.product_id AND stock_status.website_id=' . $websiteId,
@@ -211,7 +220,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      */
     public function addStockDataToCollection($collection, $isFilterInStock)
     {
-        $websiteId = $this->_storeManager->getStore($collection->getStoreId())->getWebsiteId();
+        $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
         $joinCondition = $this->getConnection()->quoteInto(
             'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
             $websiteId
@@ -245,7 +254,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      */
     public function addIsInStockFilterToCollection($collection)
     {
-        $websiteId = $this->_storeManager->getStore($collection->getStoreId())->getWebsiteId();
+        $websiteId = $this->getStockConfiguration()->getDefaultScopeId();
         $joinCondition = $this->getConnection()->quoteInto(
             'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?',
             $websiteId
@@ -325,4 +334,18 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
         }
         return $statuses;
     }
+
+    /**
+     * @return StockConfigurationInterface
+     *
+     * @deprecated
+     */
+    private function getStockConfiguration()
+    {
+        if ($this->stockConfiguration === null) {
+            $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get('Magento\CatalogInventory\Api\StockConfigurationInterface');
+        }
+        return $this->stockConfiguration;
+    }
 }
diff --git a/app/code/Magento/CatalogInventory/Model/StockIndex.php b/app/code/Magento/CatalogInventory/Model/StockIndex.php
index a30bc203c638f251e167fa5f88eb6d9eaca6ef21..226293c8205e67acd32953463485713d64729128 100644
--- a/app/code/Magento/CatalogInventory/Model/StockIndex.php
+++ b/app/code/Magento/CatalogInventory/Model/StockIndex.php
@@ -78,6 +78,7 @@ class StockIndex implements StockIndexInterface
      *
      * @param int $productId
      * @param int $scopeId
+     * @deprecated
      * @return true
      * @SuppressWarnings(PHPMD.UnusedLocalVariable)
      */
@@ -108,6 +109,7 @@ class StockIndex implements StockIndexInterface
      *
      * @param int $productId
      * @param int $websiteId
+     * @deprecated
      * @return void
      */
     public function updateProductStockStatus($productId, $websiteId)
diff --git a/app/code/Magento/CatalogInventory/Model/StockState.php b/app/code/Magento/CatalogInventory/Model/StockState.php
index a5f60dce93ca7b45d3d4c4aa8783df95e72a7d80..0c8b84d473e45a47ab2ceaf69cf5089f5818a9b3 100644
--- a/app/code/Magento/CatalogInventory/Model/StockState.php
+++ b/app/code/Magento/CatalogInventory/Model/StockState.php
@@ -52,9 +52,9 @@ class StockState implements StockStateInterface
      */
     public function verifyStock($productId, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->verifyStock($stockItem);
     }
@@ -66,9 +66,9 @@ class StockState implements StockStateInterface
      */
     public function verifyNotification($productId, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->verifyNotification($stockItem);
     }
@@ -84,9 +84,9 @@ class StockState implements StockStateInterface
      */
     public function checkQty($productId, $qty, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->checkQty($stockItem, $qty);
     }
@@ -102,9 +102,9 @@ class StockState implements StockStateInterface
      */
     public function suggestQty($productId, $qty, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->suggestQty($stockItem, $qty);
     }
@@ -118,9 +118,9 @@ class StockState implements StockStateInterface
      */
     public function getStockQty($productId, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->getStockQty($stockItem);
     }
@@ -133,9 +133,9 @@ class StockState implements StockStateInterface
      */
     public function checkQtyIncrements($productId, $qty, $websiteId = null)
     {
-        if ($websiteId === null) {
+        // if ($websiteId === null) {
             $websiteId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId);
         return $this->stockStateProvider->checkQtyIncrements($stockItem, $qty);
     }
@@ -150,9 +150,9 @@ class StockState implements StockStateInterface
      */
     public function checkQuoteItemQty($productId, $itemQty, $qtyToCheck, $origQty, $scopeId = null)
     {
-        if ($scopeId === null) {
+        // if ($scopeId === null) {
             $scopeId = $this->stockConfiguration->getDefaultScopeId();
-        }
+        // }
         $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
         return $this->stockStateProvider->checkQuoteItemQty($stockItem, $itemQty, $qtyToCheck, $origQty);
     }
diff --git a/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php b/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php
index d700b296871aa2faf5fcc62a5ef3b6822c2cbe24..72c9b35394717deb7b22b24fa89236d5e559e1bd 100644
--- a/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php
+++ b/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php
@@ -17,6 +17,7 @@ class SaveInventoryDataObserver implements ObserverInterface
 {
     /**
      * @var StockIndexInterface
+     * @deprecated
      */
     protected $stockIndex;
 
@@ -96,14 +97,7 @@ class SaveInventoryDataObserver implements ObserverInterface
     public function execute(EventObserver $observer)
     {
         $product = $observer->getEvent()->getProduct();
-
         if ($product->getStockData() === null) {
-            if ($product->getIsChangedWebsites() || $product->dataHasChangedFor('status')) {
-                $this->stockIndex->rebuild(
-                    $product->getId(),
-                    $product->getStore()->getWebsiteId()
-                );
-            }
             return $this;
         }
 
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php
index 1f1c7a98f0907a6cea0b863477a6f57af1200f7d..df5ea40e933075bb07dd398ab3514e2cf18960d6 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php
@@ -37,6 +37,11 @@ class StockTest extends \PHPUnit_Framework_TestCase
      */
     protected $statusFactoryMock;
 
+    /**
+     * @var \Magento\CatalogInventory\Api\StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $stockConfiguration;
+
     protected function setUp()
     {
         $this->stockRegistryProviderMock = $this->getMockBuilder(
@@ -55,12 +60,20 @@ class StockTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->setMethods(['create'])
             ->getMock();
+        $this->stockConfiguration = $this->getMockBuilder('Magento\CatalogInventory\Api\StockConfigurationInterface')
+            ->getMock();
         $this->stock = new Stock(
             $this->storeManagerMock,
             $this->scopeConfigMock,
             $this->statusFactoryMock,
             $this->stockRegistryProviderMock
         );
+
+        // Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793)
+        $reflection = new \ReflectionClass(get_class($this->stock));
+        $reflectionProperty = $reflection->getProperty('stockConfiguration');
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($this->stock, $this->stockConfiguration);
     }
 
     public function testAssignStatusToProduct()
@@ -77,19 +90,12 @@ class StockTest extends \PHPUnit_Framework_TestCase
         $this->stockRegistryProviderMock->expects($this->any())
             ->method('getStockStatus')
             ->willReturn($stockStatusMock);
-        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $storeMock->expects($this->once())
-            ->method('getWebsiteId')
-            ->willReturn($websiteId);
+        $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn($websiteId);
+
         $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product')
             ->disableOriginalConstructor()
-            ->setMethods(['setIsSalable', 'getStore', 'getId'])
+            ->setMethods(['setIsSalable', 'getId'])
             ->getMock();
-        $productMock->expects($this->any())
-            ->method('getStore')
-            ->willReturn($storeMock);
         $productMock->expects($this->once())
             ->method('setIsSalable')
             ->with($status);
@@ -134,12 +140,6 @@ class StockTest extends \PHPUnit_Framework_TestCase
         $productCollectionMock->expects($this->any())
             ->method('getIterator')
             ->willReturn($iteratorMock);
-        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $this->storeManagerMock->expects($this->once())
-            ->method('getStore')
-            ->willReturn($storeMock);
         $this->stockRegistryProviderMock->expects($this->once())
             ->method('getStockStatus')
             ->withAnyParameters()
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b180ba0e035173514ebb444bec4e2c4487567577
--- /dev/null
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\CatalogInventory\Test\Unit\Model\Config\Backend;
+
+class ManagestockTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var  \Magento\CatalogInventory\Model\Indexer\Stock\Processor|\PHPUnit_Framework_MockObject_MockObject */
+    protected $stockIndexerProcessor;
+
+    /** @var \Magento\CatalogInventory\Model\Config\Backend\Managestock */
+    protected $model;
+
+    protected function setUp()
+    {
+        $this->stockIndexerProcessor = $this->getMockBuilder('Magento\CatalogInventory\Model\Indexer\Stock\Processor')
+            ->disableOriginalConstructor()
+            ->getMock();
+        $this->model = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
+            'Magento\CatalogInventory\Model\Config\Backend\Managestock',
+            [
+                'stockIndexerProcessor' => $this->stockIndexerProcessor,
+            ]
+        );
+    }
+
+    /**
+     * Data provider for testSaveAndRebuildIndex
+     * @return array
+     */
+    public function saveAndRebuildIndexDataProvider()
+    {
+        return [
+            [1, 1],
+            [0, 0],
+        ];
+    }
+
+    /**
+     * @dataProvider saveAndRebuildIndexDataProvider
+     *
+     * @param int $newStockValue new value for stock status
+     * @param int $callCount count matcher
+     */
+    public function testSaveAndRebuildIndex($newStockValue, $callCount)
+    {
+        $this->model->setValue($newStockValue);
+        $this->stockIndexerProcessor->expects($this->exactly($callCount))->method('markIndexerAsInvalid');
+        $this->model->afterSave();
+    }
+}
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php
index 90b05b2d10649ce527debbea0f368d5e385f55bc..a0b2cc7225c9efe60c158b0e71946a22d5cb5512 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php
@@ -61,17 +61,7 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
 
     public function testGetDefaultWebsiteId()
     {
-        $id = 1;
-        $websiteMock = $this->getMockBuilder('Magento\Store\Model\Website')
-            ->disableOriginalConstructor()
-            ->getMock();
-        $websiteMock->expects($this->once())
-            ->method('getId')
-            ->willReturn($id);
-        $this->storeManagerMock->expects($this->once())
-            ->method('getWebsite')
-            ->willReturn($websiteMock);
-        $this->assertEquals($id, $this->model->getDefaultScopeId());
+        $this->assertEquals(0, $this->model->getDefaultScopeId());
     }
 
     public function testGetIsQtyTypeIds()
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php
index 534960b4397833d268c56ab62c9a45d46cc997f9..cb26fda9be79e928dac5585694e71778661bf0f6 100644
--- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php
+++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php
@@ -154,11 +154,7 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase
             ->method('getStockItem')
             ->willReturn(null);
 
-        $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store')
-            ->disableOriginalConstructor()->getMock();
-        $storeMock->expects($this->once())->method('getWebsiteId')->willReturn(1);
-        $this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock);
-
+        $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn(1);
         $this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItem);
         $this->stockRegistry->expects($this->once())->method('updateStockItemBySku');
 
@@ -180,11 +176,10 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase
     public function testAroundSave()
     {
         $productId = 5494;
-        $websiteId = 1;
         $storeId = 2;
         $sku = 'my product that needs saving';
         $defaultScopeId = 100;
-        $this->stockConfiguration->expects($this->once())
+        $this->stockConfiguration->expects($this->exactly(2))
             ->method('getDefaultScopeId')
             ->willReturn($defaultScopeId);
         $this->stockRegistry->expects($this->once())
@@ -209,17 +204,12 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase
             ->method('getStockItem')
             ->willReturn($storedStockItem);
 
-        $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store')
-            ->disableOriginalConstructor()->getMock();
-        $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId);
-        $this->storeManager->expects($this->once())->method('getStore')->with($storeId)->willReturn($storeMock);
-
         $this->product->expects(($this->exactly(2)))->method('getId')->willReturn($productId);
         $this->product->expects(($this->atLeastOnce()))->method('getStoreId')->willReturn($storeId);
         $this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($sku);
 
         $this->stockItem->expects($this->once())->method('setProductId')->with($productId);
-        $this->stockItem->expects($this->once())->method('setWebsiteId')->with($websiteId);
+        $this->stockItem->expects($this->once())->method('setWebsiteId')->with($defaultScopeId);
 
         $this->stockRegistry->expects($this->once())
             ->method('updateStockItemBySku')
diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php
deleted file mode 100644
index 1b8347539485d11ff30b22ea3803201cf08004f2..0000000000000000000000000000000000000000
--- a/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\CatalogInventory\Test\Unit\Observer;
-
-use Magento\CatalogInventory\Observer\SaveInventoryDataObserver;
-
-class SaveInventoryDataObserverTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * @var SaveInventoryDataObserver
-     */
-    protected $observer;
-
-    /**
-     * @var \Magento\CatalogInventory\Api\StockIndexInterface|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $stockIndex;
-
-    /**
-     * @var \Magento\Framework\Event|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $event;
-
-    /**
-     * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject
-     */
-    protected $eventObserver;
-
-    protected function setUp()
-    {
-        $this->stockIndex = $this->getMockForAbstractClass(
-            'Magento\CatalogInventory\Api\StockIndexInterface',
-            ['rebuild'],
-            '',
-            false
-        );
-
-        $this->event = $this->getMockBuilder('Magento\Framework\Event')
-            ->disableOriginalConstructor()
-            ->setMethods(['getProduct'])
-            ->getMock();
-
-        $this->eventObserver = $this->getMockBuilder('Magento\Framework\Event\Observer')
-            ->disableOriginalConstructor()
-            ->setMethods(['getEvent'])
-            ->getMock();
-
-        $this->eventObserver->expects($this->atLeastOnce())
-            ->method('getEvent')
-            ->will($this->returnValue($this->event));
-
-        $this->observer = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
-            'Magento\CatalogInventory\Observer\SaveInventoryDataObserver',
-            [
-                'stockIndex' => $this->stockIndex,
-            ]
-        );
-    }
-
-    public function testSaveInventoryData()
-    {
-        $productId = 4;
-        $websiteId = 5;
-        $stockData = null;
-        $websitesChanged = true;
-        $statusChanged = true;
-
-        $store = $this->getMock('Magento\Store\Model\Store', ['getWebsiteId'], [], '', false);
-        $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId));
-
-        $product = $this->getMock(
-            'Magento\Catalog\Model\Product',
-            ['getStockData', 'getIsChangedWebsites', 'dataHasChangedFor', 'getId', 'getStore'],
-            [],
-            '',
-            false
-        );
-        $product->expects($this->once())->method('getStockData')->will($this->returnValue($stockData));
-        $product->expects($this->any())->method('getIsChangedWebsites')->will($this->returnValue($websitesChanged));
-        $product->expects($this->any())->method('dataHasChangedFor')->will($this->returnValue($statusChanged));
-        $product->expects($this->once())->method('getId')->will($this->returnValue($productId));
-        $product->expects($this->once())->method('getStore')->will($this->returnValue($store));
-
-        $this->stockIndex->expects($this->once())->method('rebuild')->will($this->returnValue(true));
-
-        $this->event->expects($this->once())
-            ->method('getProduct')
-            ->will($this->returnValue($product));
-
-        $this->observer->execute($this->eventObserver);
-    }
-}
diff --git a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
index 72134fb16912939f5a80e42e8803fd7120e6f3a5..31ce6d550b116455052cf674e99155db3e3f7af2 100644
--- a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
+++ b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php
@@ -6,20 +6,18 @@
 
 namespace Magento\CatalogSearch\Model\Search;
 
-use Magento\CatalogSearch\Model\Search\TableMapper;
 use Magento\Framework\App\Config\ScopeConfigInterface;
 use Magento\Framework\App\ResourceConnection;
 use Magento\Framework\DB\Select;
 use Magento\Framework\Search\Adapter\Mysql\ConditionManager;
 use Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface;
 use Magento\Framework\Search\Request\Dimension;
-use Magento\Framework\Search\Request\Filter\BoolExpression;
-use Magento\Framework\Search\Request\FilterInterface;
-use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
 use Magento\Framework\Search\RequestInterface;
 use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 use Magento\Store\Model\ScopeInterface;
 use Magento\Store\Model\StoreManagerInterface;
+use Magento\CatalogInventory\Api\StockConfigurationInterface;
+use Magento\CatalogInventory\Model\Stock;
 use Magento\Framework\App\ScopeResolverInterface;
 
 /**
@@ -40,6 +38,7 @@ class IndexBuilder implements IndexBuilderInterface
 
     /**
      * @var StoreManagerInterface
+     * @deprecated
      */
     private $storeManager;
 
@@ -63,6 +62,11 @@ class IndexBuilder implements IndexBuilderInterface
      */
     private $dimensionScopeResolver;
 
+    /**
+     * @var StockConfigurationInterface
+     */
+    private $stockConfiguration;
+
     /**
      * @param \Magento\Framework\App\ResourceConnection $resource
      * @param ScopeConfigInterface $config
@@ -124,16 +128,30 @@ class IndexBuilder implements IndexBuilderInterface
                 'search_index.entity_id = stock_index.product_id'
                 . $this->resource->getConnection()->quoteInto(
                     ' AND stock_index.website_id = ?',
-                    $this->storeManager->getWebsite()->getId()
+                    $this->getStockConfiguration()->getDefaultScopeId()
                 ),
                 []
             );
-            $select->where('stock_index.stock_status = ?', 1);
+            $select->where('stock_index.stock_status = ?', Stock::DEFAULT_STOCK_ID);
         }
 
         return $select;
     }
 
+    /**
+     * @return StockConfigurationInterface
+     *
+     * @deprecated
+     */
+    private function getStockConfiguration()
+    {
+        if ($this->stockConfiguration === null) {
+            $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get('Magento\CatalogInventory\Api\StockConfigurationInterface');
+        }
+        return $this->stockConfiguration;
+    }
+
     /**
      * Add filtering by dimensions
      *
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
index 73dfd3867b0dcaf870794e6195d508309f440600..32176594936b2d996b1e14c758cf0671c76a73f5 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php
@@ -40,6 +40,9 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
     /** @var \Magento\Search\Model\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject */
     private $resource;
 
+    /** @var \Magento\CatalogInventory\Api\StockConfigurationInterface|MockObject */
+    private $stockConfiguration;
+
     /**
      * @var \Magento\CatalogSearch\Model\Search\IndexBuilder
      */
@@ -55,6 +58,10 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
      */
     private $scopeInterface;
 
+    /**
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     * @return void
+     */
     protected function setUp()
     {
         $this->select = $this->getMockBuilder('\Magento\Framework\DB\Select')
@@ -139,6 +146,9 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
             '',
             false
         );
+        $this->stockConfiguration = $this
+            ->getMockBuilder('\Magento\CatalogInventory\Api\StockConfigurationInterface')
+            ->getMock();
 
         $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->target = $objectManagerHelper->getObject(
@@ -153,6 +163,12 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
                 'dimensionScopeResolver' => $this->dimensionScopeResolver
             ]
         );
+
+        // Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793)
+        $reflection = new \ReflectionClass(get_class($this->target));
+        $reflectionProperty = $reflection->getProperty('stockConfiguration');
+        $reflectionProperty->setAccessible(true);
+        $reflectionProperty->setValue($this->target, $this->stockConfiguration);
     }
 
     public function testBuildWithOutOfStock()
@@ -198,15 +214,13 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase
 
         $this->mockBuild($index, $tableSuffix, false);
 
+        $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn(1);
         $this->config->expects($this->once())
             ->method('isSetFlag')
             ->with('cataloginventory/options/show_out_of_stock')
             ->will($this->returnValue(false));
         $this->connection->expects($this->once())->method('quoteInto')
             ->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1');
-        $website = $this->getMockBuilder('Magento\Store\Model\Website')->disableOriginalConstructor()->getMock();
-        $website->expects($this->once())->method('getId')->willReturn(1);
-        $this->storeManager->expects($this->once())->method('getWebsite')->willReturn($website);
         $this->select->expects($this->at(2))
             ->method('where')
             ->with('(someName=someValue)')
diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json
index 709009300b724a41dbca6c80773684af9c15e91e..860d5080b9bdffd0282c5b989c8373b886d498af 100644
--- a/app/code/Magento/CatalogSearch/composer.json
+++ b/app/code/Magento/CatalogSearch/composer.json
@@ -11,6 +11,7 @@
         "magento/module-eav": "100.0.*",
         "magento/module-backend": "100.0.*",
         "magento/module-theme": "100.0.*",
+        "magento/module-catalog-inventory": "100.0.*",
         "magento/framework": "100.0.*"
     },
     "type": "magento2-module",
diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php
index 386e77580fa4abab025f3119b056f08b2be88084..6f2cd40e97f7ad19fb5cd217881403a11a594268 100644
--- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php
+++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php
@@ -71,7 +71,9 @@ class Combine extends \Magento\Rule\Model\Condition\Combine
      */
     public function collectValidatedAttributes($productCollection)
     {
+        $alias = array_keys($productCollection->getSelect()->getPart('from'))[0];
         foreach ($this->getConditions() as $condition) {
+            $condition->setData('attribute', $alias . '.' . $condition->getData('attribute'));
             $condition->addToCollection($productCollection);
         }
         return $this;
diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php
index 34c14626d8bf7423d435c62e952c663a8b52f9ae..b0a3fdab8eb32c6c97ef798a94390f7a942f04a2 100644
--- a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php
+++ b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php
@@ -73,8 +73,13 @@ class CombineTest extends \PHPUnit_Framework_TestCase
     public function testCollectValidatedAttributes()
     {
         $collection = $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Product\Collection')
-            ->disableOriginalConstructor()
+            ->disableOriginalConstructor()->setMethods(['getSelect'])
+            ->getMock();
+        $select = $this->getMockBuilder('\Magento\Framework\DB\Select')
+            ->disableOriginalConstructor()->setMethods(['getPart'])
             ->getMock();
+        $select->expects($this->any())->method('getPart')->with('from')->willReturn(['alias_table' => 'table_name']);
+        $collection->expects($this->any())->method('getSelect')->willReturn($select);
         $condition = $this->getMockBuilder('Magento\CatalogWidget\Model\Rule\Condition\Combine')
             ->disableOriginalConstructor()->setMethods(['addToCollection'])
             ->getMock();
diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
index 551df288ebcb03e2941a618ec28e667265b0af99..6f2b989e5e9bfaa9fa91643b1958be6a99c0fdc1 100644
--- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
+++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php
@@ -28,19 +28,11 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer
         $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
         $connection = $this->getConnection();
         $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable();
-        $select = $connection->select()->from(['e' => $this->getTable('catalog_product_entity')], ['entity_id']);
-        $this->_addWebsiteJoinToSelect($select, true);
-        $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id');
-        $select->columns(
-            'cw.website_id'
-        )->join(
-            ['cis' => $this->getTable('cataloginventory_stock')],
-            '',
-            ['stock_id']
-        )->joinLeft(
-            ['cisi' => $this->getTable('cataloginventory_stock_item')],
-            'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id',
-            []
+        $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable);
+        $select->reset(
+            \Magento\Framework\DB\Select::COLUMNS
+        )->columns(
+            ['e.entity_id', 'cis.website_id', 'cis.stock_id']
         )->joinLeft(
             ['l' => $this->getTable('catalog_product_super_link')],
             'l.parent_id = e.' . $metadata->getLinkField(),
@@ -51,24 +43,14 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer
             []
         )->joinLeft(
             ['i' => $idxTable],
-            'i.product_id = l.product_id AND cw.website_id = i.website_id AND cis.stock_id = i.stock_id',
+            'i.product_id = l.product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id',
             []
         )->columns(
             ['qty' => new \Zend_Db_Expr('0')]
-        )->where(
-            'cw.website_id != 0'
-        )->where(
-            'e.type_id = ?',
-            $this->getTypeId()
-        )->group(
-            ['e.entity_id', 'cw.website_id', 'cis.stock_id']
         );
-        $psExpr = $this->_addAttributeToSelect($select, 'status', 'e.' . $metadata->getLinkField(), 'cs.store_id');
-        $psCond = $connection->quoteInto($psExpr . '=?', ProductStatus::STATUS_ENABLED);
-
         $statusExpr = $this->getStatusExpression($connection);
 
-        $optExpr = $connection->getCheckSql("{$psCond} AND le.required_options = 0", 'i.stock_status', 0);
+        $optExpr = $connection->getCheckSql("le.required_options = 0", 'i.stock_status', 0);
         $stockStatusExpr = $connection->getLeastSql(["MAX({$optExpr})", "MIN({$statusExpr})"]);
 
         $select->columns(['status' => $stockStatusExpr]);
diff --git a/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php b/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php
index 9587a195b5e7c67d06f8a76b89d6957b5d62c403..8a3f0f1d0e900a5f4d3283076bb6ed8831c9f47a 100644
--- a/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php
+++ b/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php
@@ -26,23 +26,12 @@ class Grouped extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stoc
     {
         $connection = $this->getConnection();
         $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable();
-        $select = $connection->select()->from(
-            ['e' => $this->getTable('catalog_product_entity')],
-            ['entity_id']
-        );
-        $this->_addWebsiteJoinToSelect($select, true);
-        $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id');
         $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class);
-        $select->columns(
-            'cw.website_id'
-        )->join(
-            ['cis' => $this->getTable('cataloginventory_stock')],
-            '',
-            ['stock_id']
-        )->joinLeft(
-            ['cisi' => $this->getTable('cataloginventory_stock_item')],
-            'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id',
-            []
+        $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable);
+        $select->reset(
+            \Magento\Framework\DB\Select::COLUMNS
+        )->columns(
+            ['e.entity_id', 'cis.website_id', 'cis.stock_id']
         )->joinLeft(
             ['l' => $this->getTable('catalog_product_link')],
             'e.' . $metadata->getLinkField() . ' = l.product_id AND l.link_type_id=' .
@@ -54,31 +43,15 @@ class Grouped extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stoc
             []
         )->joinLeft(
             ['i' => $idxTable],
-            'i.product_id = l.linked_product_id AND cw.website_id = i.website_id AND cis.stock_id = i.stock_id',
+            'i.product_id = l.linked_product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id',
             []
         )->columns(
             ['qty' => new \Zend_Db_Expr('0')]
-        )->where(
-            'cw.website_id != 0'
-        )->where(
-            'e.type_id = ?',
-            $this->getTypeId()
-        )->group(
-            ['e.entity_id', 'cw.website_id', 'cis.stock_id']
-        );
-
-        // add limitation of status
-        $productStatusExpr = $this->_addAttributeToSelect(
-            $select,
-            'status',
-            'e.' . $metadata->getLinkField(),
-            'cs.store_id'
         );
-        $productStatusCond = $connection->quoteInto($productStatusExpr . '=?', ProductStatus::STATUS_ENABLED);
 
         $statusExpression = $this->getStatusExpression($connection);
 
-        $optExpr = $connection->getCheckSql("{$productStatusCond} AND le.required_options = 0", 'i.stock_status', 0);
+        $optExpr = $connection->getCheckSql("le.required_options = 0", 'i.stock_status', 0);
         $stockStatusExpr = $connection->getLeastSql(["MAX({$optExpr})", "MIN({$statusExpression})"]);
 
         $select->columns(['status' => $stockStatusExpr]);
diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php
index d0205f51453bc4d003e6347af7b5754ac40d6d4c..52a4714fea8db053b49790a548538644866744cc 100644
--- a/app/code/Magento/Theme/Block/Html/Topmenu.php
+++ b/app/code/Magento/Theme/Block/Html/Topmenu.php
@@ -330,7 +330,9 @@ class Topmenu extends Template implements IdentityInterface
      */
     public function addIdentity($identity)
     {
-        $this->identities[] = $identity;
+        if (!in_array($identity, $this->identities)) {
+            $this->identities[] = $identity;
+        }
     }
 
     /**
@@ -364,4 +366,14 @@ class Topmenu extends Template implements IdentityInterface
     {
         return array_merge(parent::getCacheTags(), $this->getIdentities());
     }
+
+    /**
+     * Get menu object.
+     *
+     * @return Node
+     */
+    public function getMenu()
+    {
+        return $this->_menu;
+    }
 }
diff --git a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
index d5c0bcc678f6a4af813fe88d6f2419f9561a5134..038f5cdcfc444802259049eac10e371fba17edec 100644
--- a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
+++ b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php
@@ -12,6 +12,7 @@ use Magento\Webapi\Model\Soap\Wsdl;
 use Magento\Webapi\Model\Soap\WsdlFactory;
 use Magento\Framework\Webapi\Authorization;
 use Magento\Webapi\Model\ServiceMetadata;
+use Magento\Framework\Exception\AuthorizationException;
 
 /**
  * WSDL generator.
@@ -364,4 +365,21 @@ class Generator extends AbstractSchemaGenerator
     {
         return $this->serviceMetadata->getServiceMetadata($serviceName);
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getAllowedServicesMetadata($requestedServices)
+    {
+        $allowedServicesMetadata = parent::getAllowedServicesMetadata($requestedServices);
+        if (!$allowedServicesMetadata) {
+            throw new AuthorizationException(
+                __(
+                    AuthorizationException::NOT_AUTHORIZED,
+                    ['resources' => implode(', ', $requestedServices)]
+                )
+            );
+        }
+        return $allowedServicesMetadata;
+    }
 }
diff --git a/composer.json b/composer.json
index 73115b15a9f32a8af1a49a14a7658cd5daf9804c..3734cdd372bba9951c78de4769fa6773429b1290 100644
--- a/composer.json
+++ b/composer.json
@@ -33,7 +33,7 @@
         "zendframework/zend-http": "~2.4.6",
         "magento/zendframework1": "1.12.16",
         "colinmollenhour/credis": "1.6",
-        "colinmollenhour/php-redis-session-abstract": "1.0",
+        "colinmollenhour/php-redis-session-abstract": "1.1",
         "composer/composer": "1.0.0-beta1",
         "monolog/monolog": "1.16.0",
         "oyejorge/less.php": "1.7.0.3",
diff --git a/composer.lock b/composer.lock
index 4aaae63b403d43bf5ce7a75886dc6c8cedb6adb0..2f0873b997487361830407de6878ee657eab5928 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "d81a16c234a62403d9b5b06057393d9d",
-    "content-hash": "cd415001aebab7eb87bb62e2223509fc",
+    "hash": "666640f73320778f40be99a86695ef1c",
+    "content-hash": "1a3c1d3316e4448159bbcc436015ad2b",
     "packages": [
         {
             "name": "braintree/braintree_php",
@@ -95,16 +95,16 @@
         },
         {
             "name": "colinmollenhour/php-redis-session-abstract",
-            "version": "v1.0",
+            "version": "v1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/colinmollenhour/php-redis-session-abstract.git",
-                "reference": "1308ddc08e2adbe303f7f8b8ead9beb5f2f2adf9"
+                "reference": "95330b7f29663dab81f53d1a438e4d927b6c5f66"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/1308ddc08e2adbe303f7f8b8ead9beb5f2f2adf9",
-                "reference": "1308ddc08e2adbe303f7f8b8ead9beb5f2f2adf9",
+                "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/95330b7f29663dab81f53d1a438e4d927b6c5f66",
+                "reference": "95330b7f29663dab81f53d1a438e4d927b6c5f66",
                 "shasum": ""
             },
             "require": {
@@ -129,7 +129,7 @@
             ],
             "description": "A Redis-based session handler with optimistic locking",
             "homepage": "https://github.com/colinmollenhour/php-redis-session-abstract",
-            "time": "2016-01-14 16:04:27"
+            "time": "2016-02-03 18:13:49"
         },
         {
             "name": "composer/composer",
@@ -208,16 +208,16 @@
         },
         {
             "name": "composer/semver",
-            "version": "1.3.0",
+            "version": "1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/semver.git",
-                "reference": "df4463baa9f44fe6cf0a6da4fde2934d4c0a2747"
+                "reference": "84c47f3d8901440403217afc120683c7385aecb8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/semver/zipball/df4463baa9f44fe6cf0a6da4fde2934d4c0a2747",
-                "reference": "df4463baa9f44fe6cf0a6da4fde2934d4c0a2747",
+                "url": "https://api.github.com/repos/composer/semver/zipball/84c47f3d8901440403217afc120683c7385aecb8",
+                "reference": "84c47f3d8901440403217afc120683c7385aecb8",
                 "shasum": ""
             },
             "require": {
@@ -266,28 +266,28 @@
                 "validation",
                 "versioning"
             ],
-            "time": "2016-02-25 22:23:39"
+            "time": "2016-03-30 13:16:03"
         },
         {
             "name": "composer/spdx-licenses",
-            "version": "1.1.2",
+            "version": "1.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/spdx-licenses.git",
-                "reference": "9e1c3926bb0842812967213d7c92827bc5883671"
+                "reference": "547659c3cacd3ccfe1b4714c2ff88cafc6b6793b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/9e1c3926bb0842812967213d7c92827bc5883671",
-                "reference": "9e1c3926bb0842812967213d7c92827bc5883671",
+                "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/547659c3cacd3ccfe1b4714c2ff88cafc6b6793b",
+                "reference": "547659c3cacd3ccfe1b4714c2ff88cafc6b6793b",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.2"
+                "php": "^5.3.2 || ^7.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "~4.5",
-                "phpunit/phpunit-mock-objects": "~2.3"
+                "phpunit/phpunit": "^4.5 || ^5.0.5",
+                "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
             },
             "type": "library",
             "extra": {
@@ -327,7 +327,7 @@
                 "spdx",
                 "validator"
             ],
-            "time": "2015-10-05 11:27:42"
+            "time": "2016-03-25 10:57:10"
         },
         {
             "name": "justinrainbow/json-schema",
@@ -1181,16 +1181,16 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3"
+                "reference": "47d2d8cade9b1c3987573d2943bb9352536cdb87"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3",
-                "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/47d2d8cade9b1c3987573d2943bb9352536cdb87",
+                "reference": "47d2d8cade9b1c3987573d2943bb9352536cdb87",
                 "shasum": ""
             },
             "require": {
@@ -1237,20 +1237,20 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2016-01-27 05:14:19"
+            "time": "2016-03-07 14:04:32"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "65cb36b6539b1d446527d60457248f30d045464d"
+                "reference": "f08ffdf229252cd2745558cb2112df43903bcae4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/65cb36b6539b1d446527d60457248f30d045464d",
-                "reference": "65cb36b6539b1d446527d60457248f30d045464d",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/f08ffdf229252cd2745558cb2112df43903bcae4",
+                "reference": "f08ffdf229252cd2745558cb2112df43903bcae4",
                 "shasum": ""
             },
             "require": {
@@ -1286,20 +1286,20 @@
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2016-02-22 15:02:30"
+            "time": "2016-03-27 10:20:16"
         },
         {
             "name": "symfony/finder",
-            "version": "v3.0.3",
+            "version": "v3.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723"
+                "reference": "c54e407b35bc098916704e9fd090da21da4c4f52"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/623bda0abd9aa29e529c8e9c08b3b84171914723",
-                "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/c54e407b35bc098916704e9fd090da21da4c4f52",
+                "reference": "c54e407b35bc098916704e9fd090da21da4c4f52",
                 "shasum": ""
             },
             "require": {
@@ -1335,20 +1335,20 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2016-01-27 05:14:46"
+            "time": "2016-03-10 11:13:05"
         },
         {
             "name": "symfony/process",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe"
+                "reference": "fb467471952ef5cf8497c029980e556b47545333"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
-                "reference": "7dedd5b60550f33dca16dd7e94ef8aca8b67bbfe",
+                "url": "https://api.github.com/repos/symfony/process/zipball/fb467471952ef5cf8497c029980e556b47545333",
+                "reference": "fb467471952ef5cf8497c029980e556b47545333",
                 "shasum": ""
             },
             "require": {
@@ -1384,7 +1384,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2016-02-02 13:33:15"
+            "time": "2016-03-23 13:11:46"
         },
         {
             "name": "tedivm/jshrink",
@@ -4112,16 +4112,16 @@
         },
         {
             "name": "symfony/config",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19"
+                "reference": "5273f4724dc5288fe7a33cb08077ab9852621f2c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19",
-                "reference": "0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19",
+                "url": "https://api.github.com/repos/symfony/config/zipball/5273f4724dc5288fe7a33cb08077ab9852621f2c",
+                "reference": "5273f4724dc5288fe7a33cb08077ab9852621f2c",
                 "shasum": ""
             },
             "require": {
@@ -4161,20 +4161,20 @@
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2016-02-22 16:12:45"
+            "time": "2016-03-04 07:54:35"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "62251761a7615435b22ccf562384c588b431be44"
+                "reference": "f7b4a498e679fa440b16facb934680a1527ed48c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/62251761a7615435b22ccf562384c588b431be44",
-                "reference": "62251761a7615435b22ccf562384c588b431be44",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f7b4a498e679fa440b16facb934680a1527ed48c",
+                "reference": "f7b4a498e679fa440b16facb934680a1527ed48c",
                 "shasum": ""
             },
             "require": {
@@ -4223,20 +4223,20 @@
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2016-02-28 16:34:46"
+            "time": "2016-03-21 07:27:21"
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v3.0.3",
+            "version": "v3.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/stopwatch.git",
-                "reference": "4a204804952ff267ace88cf499e0b4bb302a475e"
+                "reference": "6015187088421e9499d8f8316bdb396f8b806c06"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4a204804952ff267ace88cf499e0b4bb302a475e",
-                "reference": "4a204804952ff267ace88cf499e0b4bb302a475e",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6015187088421e9499d8f8316bdb396f8b806c06",
+                "reference": "6015187088421e9499d8f8316bdb396f8b806c06",
                 "shasum": ""
             },
             "require": {
@@ -4272,20 +4272,20 @@
             ],
             "description": "Symfony Stopwatch Component",
             "homepage": "https://symfony.com",
-            "time": "2016-01-03 15:35:16"
+            "time": "2016-03-04 07:55:57"
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.8.3",
+            "version": "v2.8.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
-                "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995"
+                "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/2a4ee40acb880c56f29fb1b8886e7ffe94f3b995",
-                "reference": "2a4ee40acb880c56f29fb1b8886e7ffe94f3b995",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/584e52cb8f788a887553ba82db6caacb1d6260bb",
+                "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb",
                 "shasum": ""
             },
             "require": {
@@ -4321,7 +4321,7 @@
             ],
             "description": "Symfony Yaml Component",
             "homepage": "https://symfony.com",
-            "time": "2016-02-23 07:41:20"
+            "time": "2016-03-04 07:54:35"
         },
         {
             "name": "theseer/fdomdocument",
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php
index eff0dbba735f6295e4084f10bb8228f56ee04539..88d4e559e16d52967f1d452bfd95791765cd1255 100644
--- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php
@@ -25,7 +25,7 @@ abstract class BaseService extends \Magento\TestFramework\TestCase\WebapiAbstrac
             $this->_assertSoapException(
                 $serviceInfo,
                 $requestData,
-                'SOAP-ERROR: Parsing WSDL: Couldn\'t bind to service'
+                'Consumer is not authorized to access %resources'
             );
         } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
             $this->_assertRestUnauthorizedException($serviceInfo, $requestData);
@@ -111,7 +111,7 @@ abstract class BaseService extends \Magento\TestFramework\TestCase\WebapiAbstrac
             }
 
             if ($expectedMessage) {
-                $this->assertEquals($expectedMessage, $e->getMessage());
+                $this->assertContains($expectedMessage, $e->getMessage());
             }
         }
     }
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php
index c7ef1d00e02fad6a9311240065b3c32a247e2065..8cd95ef23a47e75b7915e7c114c1968833d81125 100644
--- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php
@@ -110,8 +110,8 @@ class SoapErrorHandlingTest extends \Magento\TestFramework\TestCase\WebapiAbstra
         } catch (\SoapFault $e) {
             $this->checkSoapFault(
                 $e,
-                'SOAP-ERROR: Parsing WSDL: Couldn\'t bind to service',
-                'WSDL'
+                'Consumer is not authorized to access %resources',
+                'env:Sender'
             );
         }
     }
diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php
index 2593e9d12f5f94c4e18f12e3f9720747994e1b56..9afdb1f26067a769726fd4d44f235d3c5958ba48 100644
--- a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php
@@ -65,6 +65,16 @@ class WsdlGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\W
         $this->_checkFaultsDeclaration($wsdlContent);
     }
 
+    public function testNoAuthorizedServices()
+    {
+        $wsdlUrl = $this->_getBaseWsdlUrl() . 'testModule5AllSoapAndRestV2';
+        $connection = curl_init($wsdlUrl);
+        curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
+        $responseContent = curl_exec($connection);
+        $this->assertEquals(curl_getinfo($connection, CURLINFO_HTTP_CODE), 401);
+        $this->assertContains("Consumer is not authorized to access %resources", $responseContent);
+    }
+
     public function testInvalidWsdlUrlNoServices()
     {
         $responseContent = $this->_getWsdlContent($this->_getBaseWsdlUrl());
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php
index 8146a04b34398a758c815c787feb9cfe047c786d..2ae37ed9b71946b9924064a3cd1fa0a30e6b3c88 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php
@@ -80,6 +80,11 @@ foreach ($prices as $price) {
         'simple-' . $productId
     )->setPrice(
         $price
+    )->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
     )->setWeight(
         18
     )->setCategoryIds(
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php
index 4992805824538bc35ec803abea5056b6456bb134..7ec85f110a5b58bc9c721593e50e2c6fb4fbb682 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php
@@ -16,4 +16,9 @@ $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL)
     ->setTaxClassId(0)
     ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
     ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->save();
+    ->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
+    )->save();
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php
deleted file mode 100644
index 12aae4429203d85c9095ba607dfe25f620852353..0000000000000000000000000000000000000000
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-namespace Magento\CatalogInventory\Model\Config\Backend;
-
-use Magento\TestFramework\Helper\Bootstrap as Bootstrap;
-
-/**
- * Class ManagestockTest
- */
-class ManagestockTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * Data provider for testSaveAndRebuildIndex
-     * @return array
-     */
-    public function saveAndRebuildIndexDataProvider()
-    {
-        return [
-            [1, 1],
-            [0, 0],
-        ];
-    }
-
-    /**
-     * Test rebuild stock indexer on stock status config save
-     *
-     * @dataProvider saveAndRebuildIndexDataProvider
-     *
-     * @magentoAppIsolation enabled
-     * @magentoDbIsolation enabled
-     * @magentoConfigFixture default/cataloginventory/item_options/manage_stock 0
-     *
-     * @param int $newStockValue new value for stock status
-     * @param int $callCount count matcher
-     */
-    public function testSaveAndRebuildIndex($newStockValue, $callCount)
-    {
-        /** @var \Magento\CatalogInventory\Model\StockIndex */
-        $stockManagement = $this->getMock(
-            '\Magento\CatalogInventory\Model\StockIndex',
-            ['rebuild'],
-            [],
-            '',
-            false
-        );
-
-        $stockManagement->expects($this->exactly($callCount))
-            ->method('rebuild');
-
-        $manageStock = new Managestock(
-            Bootstrap::getObjectManager()->get('Magento\Framework\Model\Context'),
-            Bootstrap::getObjectManager()->get('Magento\Framework\Registry'),
-            Bootstrap::getObjectManager()->get('Magento\Framework\App\Config\ScopeConfigInterface'),
-            Bootstrap::getObjectManager()->get('Magento\Framework\App\Cache\TypeListInterface'),
-            $stockManagement,
-            Bootstrap::getObjectManager()->get('Magento\CatalogInventory\Model\Indexer\Stock\Processor'),
-            Bootstrap::getObjectManager()->get('Magento\Config\Model\ResourceModel\Config')
-        );
-
-        $manageStock->setPath('cataloginventory/item_options/manage_stock');
-        $manageStock->setScope('default');
-        $manageStock->setScopeId(0);
-        $manageStock->setValue($newStockValue);
-
-        // assert
-        $manageStock->save();
-    }
-}
diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php
index 8fbcad5267cf774401910a63b7dcf7b2c8bcd427..02ddb8e23b9924bc2acd357831724196ae1fbcf8 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php
@@ -17,12 +17,19 @@ class DefaultStockTest extends \PHPUnit_Framework_TestCase
      */
     private $indexer;
 
+    /**
+     * @var \Magento\CatalogInventory\Api\StockConfigurationInterface
+     */
+    private $stockConfiguration;
+
     protected function setUp()
     {
         $this->indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\DefaultStock::class
         );
-
+        $this->stockConfiguration = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+            \Magento\CatalogInventory\Api\StockConfigurationInterface::class
+        );
     }
 
     /**
@@ -53,7 +60,7 @@ class DefaultStockTest extends \PHPUnit_Framework_TestCase
         );
         $criteria = $criteriaFactory->create();
         $criteria->setProductsFilter([$product->getId()]);
-        $criteria->addFilter('website', 'website_id', $testWebsite->getId());
+        $criteria->addFilter('website', 'website_id', $this->stockConfiguration->getDefaultScopeId());
         $items = $stockStatusRepository->getList($criteria)->getItems();
         $this->assertEquals($product->getId(), $items[$product->getId()]->getProductId());
     }
diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php
index 7ccfba9b3c1b7cf743cfeb30512ffc11902ddf80..4c15a2a9e08877c2b3516ad86f5458df7ed5acd3 100644
--- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php
+++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php
@@ -17,7 +17,13 @@ $product
     ->setPrice(10)
     ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
     ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->setLinksPurchasedSeparately(true);
+    ->setLinksPurchasedSeparately(true)
+    ->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
+    );
 
 /**
  * @var \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkFactory
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
index c94078c41d741682c467819a704610ec5cdad799..8fb3c96eae0b5993b4ec93b3eac13cfccb2de97e 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php
@@ -28,7 +28,12 @@ $product->setTypeId('simple')
     ->setPrice(10)
     ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
     ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->save();
+    ->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
+    )->save();
 $product->load(1);
 
 $billingData = [
diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php
index 2304dcdc21399e3dbe7936c83fc880ab06b38139..95f387213d16ccb97ffb4d41321cd2aa941f8fef 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php
@@ -17,7 +17,12 @@ $product->setTypeId('simple')
     ->setMetaDescription('meta description')
     ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
     ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
-    ->save();
+    ->setStockData(
+        [
+            'qty' => 100,
+            'is_in_stock' => 1,
+        ]
+    )->save();
 
 $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
     ->create('Magento\Catalog\Api\ProductRepositoryInterface');
diff --git a/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php b/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php
index d4dce686583b060b6e98a8335bf96d9c04608598..1a23e2974f568d90c33d49067cc228f8666d6705 100644
--- a/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php
+++ b/lib/internal/Magento/Framework/Session/SaveHandler/Redis/Config.php
@@ -5,9 +5,14 @@
  */
 namespace Magento\Framework\Session\SaveHandler\Redis;
 
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Store\Model\ScopeInterface as StoreScopeInterface;
 use Magento\Framework\App\DeploymentConfig;
 use Magento\Framework\App\State;
 
+/**
+ * Redis session save handler
+ */
 class Config implements \Cm\RedisSession\Handler\ConfigInterface
 {
     /**
@@ -95,6 +100,21 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface
      */
     const PARAM_BREAK_AFTER             = 'session/redis/break_after';
 
+    /**
+     * Cookie lifetime config path
+     */
+    const XML_PATH_COOKIE_LIFETIME = 'web/cookie/cookie_lifetime';
+
+    /**
+     * Admin session lifetime config path
+     */
+    const XML_PATH_ADMIN_SESSION_LIFETIME = 'admin/security/session_lifetime';
+
+    /**
+     * Session max lifetime
+     */
+    const SESSION_MAX_LIFETIME = 31536000;
+
     /**
      * Deployment config
      *
@@ -102,14 +122,24 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface
      */
     private $deploymentConfig;
 
+    /**
+     * @var ScopeConfigInterface
+     */
+    private $scopeConfig;
+
     /**
      * @param DeploymentConfig $deploymentConfig
      * @param State $appState
+     * @param ScopeConfigInterface $scopeConfig
      */
-    public function __construct(DeploymentConfig $deploymentConfig, State $appState)
-    {
+    public function __construct(
+        DeploymentConfig $deploymentConfig,
+        State $appState,
+        ScopeConfigInterface $scopeConfig
+    ) {
         $this->deploymentConfig = $deploymentConfig;
         $this->appState = $appState;
+        $this->scopeConfig = $scopeConfig;
     }
 
     /**
@@ -197,7 +227,7 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface
      */
     public function getMaxLifetime()
     {
-        return $this->deploymentConfig->get(self::PARAM_MAX_LIFETIME);
+        return self::SESSION_MAX_LIFETIME;
     }
 
     /**
@@ -247,4 +277,15 @@ class Config implements \Cm\RedisSession\Handler\ConfigInterface
     {
         return $this->deploymentConfig->get(self::PARAM_BREAK_AFTER . '_' . $this->appState->getAreaCode());
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getLifetime()
+    {
+        if ($this->appState->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) {
+            return (int)$this->scopeConfig->getValue(self::XML_PATH_ADMIN_SESSION_LIFETIME);
+        }
+        return (int)$this->scopeConfig->getValue(self::XML_PATH_COOKIE_LIFETIME, StoreScopeInterface::SCOPE_STORE);
+    }
 }
diff --git a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php
index f34ef8b756d3343620ce736529a089032ca0a403..c66c31d2fcdff67dcf11b21f35cb3a26c45950db 100644
--- a/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php
+++ b/lib/internal/Magento/Framework/Session/Test/Unit/SaveHandler/Redis/ConfigTest.php
@@ -5,35 +5,44 @@
  */
 namespace Magento\Framework\Session\Test\Unit\SaveHandler\Redis;
 
+use Magento\Store\Model\ScopeInterface;
 use Magento\Framework\Session\SaveHandler\Redis\Config;
 
 class ConfigTest extends \PHPUnit_Framework_TestCase
 {
     /**
-     * @var \Magento\Framework\App\DeploymentConfig
+     * @var \Magento\Framework\App\DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $deploymentConfig;
+    private $deploymentConfigMock;
 
     /**
-     * @var \Magento\Framework\App\State
+     * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $appState;
+    private $appStateMock;
 
     /**
-     * @var \Magento\Framework\Session\SaveHandler\Redis\Config
+     * @var \Magento\Framework\App\Config|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $config;
+    private $scopeConfigMock;
+
+    /**
+     * @var Config
+     */
+    private $config;
 
     public function setUp()
     {
-        $this->deploymentConfig = $this->getMock('Magento\Framework\App\DeploymentConfig', [], [], '', false);
-        $this->appState = $this->getMock('Magento\Framework\App\State', [], [], '', false);
+        $this->deploymentConfigMock = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false);
+        $this->appStateMock = $this->getMock(\Magento\Framework\App\State::class, [], [], '', false);
+        $this->scopeConfigMock = $this->getMock(\Magento\Framework\App\Config::class, [], [], '', false);
+
         $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
         $this->config = $objectManager->getObject(
-            'Magento\Framework\Session\SaveHandler\Redis\Config',
+            Config::class,
             [
-                'deploymentConfig' => $this->deploymentConfig,
-                'appState' => $this->appState
+                'deploymentConfig' => $this->deploymentConfigMock,
+                'appState' => $this->appStateMock,
+                'scopeConfig' => $this->scopeConfigMock
             ]
         );
     }
@@ -41,7 +50,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetLogLevel()
     {
         $expected = 2;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_LOG_LEVEL)
             ->willReturn($expected);
@@ -51,7 +60,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetHost()
     {
         $expected = '127.0.0.1';
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_HOST)
             ->willReturn($expected);
@@ -61,7 +70,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetPort()
     {
         $expected = 1234;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_PORT)
             ->willReturn($expected);
@@ -71,7 +80,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetDatabase()
     {
         $expected = 2;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_DATABASE)
             ->willReturn($expected);
@@ -81,7 +90,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetPassword()
     {
         $expected = 'password';
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_PASSWORD)
             ->willReturn($expected);
@@ -91,7 +100,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetTimeout()
     {
         $expected = 10;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_TIMEOUT)
             ->willReturn($expected);
@@ -101,7 +110,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetPersistentIdentifier()
     {
         $expected = 'sess01';
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_PERSISTENT_IDENTIFIER)
             ->willReturn($expected);
@@ -111,7 +120,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetCompressionThreshold()
     {
         $expected = 2;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_COMPRESSION_THRESHOLD)
             ->willReturn($expected);
@@ -121,7 +130,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetCompressionLibrary()
     {
         $expected = 'gzip';
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_COMPRESSION_LIBRARY)
             ->willReturn($expected);
@@ -131,7 +140,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetMaxConcurrency()
     {
         $expected = 6;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_MAX_CONCURRENCY)
             ->willReturn($expected);
@@ -140,18 +149,13 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
 
     public function testGetMaxLifetime()
     {
-        $expected = 30;
-        $this->deploymentConfig->expects($this->once())
-            ->method('get')
-            ->with(Config::PARAM_MAX_LIFETIME)
-            ->willReturn($expected);
-        $this->assertEquals($this->config->getMaxLifetime(), $expected);
+        $this->assertEquals($this->config->getMaxLifetime(), Config::SESSION_MAX_LIFETIME);
     }
 
     public function testGetMinLifetime()
     {
         $expected = 30;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_MIN_LIFETIME)
             ->willReturn($expected);
@@ -161,7 +165,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetDisableLocking()
     {
         $expected = false;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_DISABLE_LOCKING)
             ->willReturn($expected);
@@ -171,7 +175,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetBotLifetime()
     {
         $expected = 30;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_BOT_LIFETIME)
             ->willReturn($expected);
@@ -181,7 +185,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetBotFirstLifetime()
     {
         $expected = 30;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_BOT_FIRST_LIFETIME)
             ->willReturn($expected);
@@ -191,7 +195,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     public function testGetFirstLifetime()
     {
         $expected = 30;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_FIRST_LIFETIME)
             ->willReturn($expected);
@@ -202,13 +206,44 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
     {
         $areaCode = 'frontend';
         $breakAfter = 5;
-        $this->deploymentConfig->expects($this->once())
+        $this->deploymentConfigMock->expects($this->once())
             ->method('get')
             ->with(Config::PARAM_BREAK_AFTER . '_' . $areaCode)
             ->willReturn($breakAfter);
-        $this->appState->expects($this->once())
+        $this->appStateMock->expects($this->once())
             ->method('getAreaCode')
             ->willReturn($areaCode);
         $this->assertEquals($this->config->getBreakAfter(), $breakAfter);
     }
+
+    public function testGetLifetimeAdmin()
+    {
+        $areaCode = 'adminhtml';
+        $expectedLifetime = 123;
+        $this->appStateMock->expects($this->once())
+            ->method('getAreaCode')
+            ->willReturn($areaCode);
+        $this->scopeConfigMock->expects($this->once())
+            ->method('getValue')
+            ->with(Config::XML_PATH_ADMIN_SESSION_LIFETIME)
+            ->willReturn($expectedLifetime);
+        $this->assertEquals($this->config->getLifetime(), $expectedLifetime);
+    }
+
+    public function testGetLifetimeFrontend()
+    {
+        $areaCode = 'frontend';
+        $expectedLifetime = 234;
+        $this->appStateMock->expects($this->once())
+            ->method('getAreaCode')
+            ->willReturn($areaCode);
+        $this->scopeConfigMock->expects($this->once())
+            ->method('getValue')
+            ->with(
+                Config::XML_PATH_COOKIE_LIFETIME,
+                ScopeInterface::SCOPE_STORE
+            )
+            ->willReturn($expectedLifetime);
+        $this->assertEquals($this->config->getLifetime(), $expectedLifetime);
+    }
 }
diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php
index bad169e114754ee24dd850c636b2f27b3e9e76d0..ee5a42069fb0cca56c7bac2065ec7f3ac6607182 100644
--- a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php
+++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php
@@ -6,7 +6,7 @@
 namespace Magento\Setup\Module\Di\Code\Reader;
 
 use Magento\Framework\Exception\FileSystemException;
-use Zend\Code\Scanner\FileScanner;
+use Magento\Setup\Module\Di\Code\Reader\FileScanner;
 
 class ClassesScanner implements ClassesScannerInterface
 {
diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php
new file mode 100644
index 0000000000000000000000000000000000000000..5293b782064242a571cb7580835abb6586d2a454
--- /dev/null
+++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php
@@ -0,0 +1,367 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+// @codingStandardsIgnoreFile
+
+namespace Magento\Setup\Module\Di\Code\Reader;
+
+/**
+ * @SuppressWarnings(PHPMD)
+ */
+class FileScanner extends \Zend\Code\Scanner\FileScanner
+{
+    /**
+     * @var int
+     */
+    private $tokenType;
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function scan()
+    {
+        if ($this->isScanned) {
+            return;
+        }
+
+        if (!$this->tokens) {
+            throw new \Zend\Code\Exception\RuntimeException('No tokens were provided');
+        }
+
+        /**
+         * Define PHP 5.4 'trait' token constant.
+         */
+        if (!defined('T_TRAIT')) {
+            define('T_TRAIT', 42001);
+        }
+
+        /**
+         * Variables & Setup
+         */
+
+        $tokens = &$this->tokens; // localize
+        $infos = &$this->infos; // localize
+        $tokenIndex = null;
+        $token = null;
+        $this->tokenType = null;
+        $tokenContent = null;
+        $tokenLine = null;
+        $namespace = null;
+        $docCommentIndex = false;
+        $infoIndex = 0;
+
+        /*
+         * MACRO creation
+         */
+        $MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenContent, &$tokenLine) {
+            $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
+            if (!isset($tokens[$tokenIndex])) {
+                $token = false;
+                $tokenContent = false;
+                $this->tokenType = false;
+                $tokenLine = false;
+
+                return false;
+            }
+            if (is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"') {
+                do {
+                    $tokenIndex++;
+                } while (!(is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"'));
+            }
+            $token = $tokens[$tokenIndex];
+            if (is_array($token)) {
+                list($this->tokenType, $tokenContent, $tokenLine) = $token;
+            } else {
+                $this->tokenType = null;
+                $tokenContent = $token;
+            }
+
+            return $tokenIndex;
+        };
+        $MACRO_TOKEN_LOGICAL_START_INDEX = function () use (&$tokenIndex, &$docCommentIndex) {
+            return ($docCommentIndex === false) ? $tokenIndex : $docCommentIndex;
+        };
+        $MACRO_DOC_COMMENT_START = function () use (&$tokenIndex, &$docCommentIndex) {
+            $docCommentIndex = $tokenIndex;
+
+            return $docCommentIndex;
+        };
+        $MACRO_DOC_COMMENT_VALIDATE = function () use (&$docCommentIndex) {
+            static $validTrailingTokens = null;
+            if ($validTrailingTokens === null) {
+                $validTrailingTokens = array(T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION);
+            }
+            if ($docCommentIndex !== false && !in_array($this->tokenType, $validTrailingTokens)) {
+                $docCommentIndex = false;
+            }
+
+            return $docCommentIndex;
+        };
+        $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
+            $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
+            $infos[$infoIndex]['lineEnd'] = $tokenLine;
+            $infoIndex++;
+
+            return $infoIndex;
+        };
+
+        /**
+         * START FINITE STATE MACHINE FOR SCANNING TOKENS
+         */
+
+        // Initialize token
+        $MACRO_TOKEN_ADVANCE();
+
+        SCANNER_TOP:
+
+        if ($token === false) {
+            goto SCANNER_END;
+        }
+
+        // Validate current doc comment index
+        $MACRO_DOC_COMMENT_VALIDATE();
+
+        switch ($this->tokenType) {
+
+            case T_DOC_COMMENT:
+
+                $MACRO_DOC_COMMENT_START();
+                goto SCANNER_CONTINUE;
+            //goto no break needed
+
+            case T_NAMESPACE:
+
+                $infos[$infoIndex] = array(
+                    'type' => 'namespace',
+                    'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(),
+                    'tokenEnd' => null,
+                    'lineStart' => $token[2],
+                    'lineEnd' => null,
+                    'namespace' => null,
+                );
+
+                // start processing with next token
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+
+                SCANNER_NAMESPACE_TOP:
+
+                if ($this->tokenType === null && $tokenContent === ';' || $tokenContent === '{') {
+                    goto SCANNER_NAMESPACE_END;
+                }
+
+                if ($this->tokenType === T_WHITESPACE) {
+                    goto SCANNER_NAMESPACE_CONTINUE;
+                }
+
+                if ($this->tokenType === T_NS_SEPARATOR || $this->tokenType === T_STRING) {
+                    $infos[$infoIndex]['namespace'] .= $tokenContent;
+                }
+
+                SCANNER_NAMESPACE_CONTINUE:
+
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+                goto SCANNER_NAMESPACE_TOP;
+
+                SCANNER_NAMESPACE_END:
+
+                $namespace = $infos[$infoIndex]['namespace'];
+
+                $MACRO_INFO_ADVANCE();
+                goto SCANNER_CONTINUE;
+            //goto no break needed
+
+            case T_USE:
+
+                $infos[$infoIndex] = array(
+                    'type' => 'use',
+                    'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(),
+                    'tokenEnd' => null,
+                    'lineStart' => $tokens[$tokenIndex][2],
+                    'lineEnd' => null,
+                    'namespace' => $namespace,
+                    'statements' => array(0 => array('use' => null,
+                        'as' => null)),
+                );
+
+                $useStatementIndex = 0;
+                $useAsContext = false;
+
+                // start processing with next token
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+
+                SCANNER_USE_TOP:
+
+                if ($this->tokenType === null) {
+                    if ($tokenContent === ';') {
+                        goto SCANNER_USE_END;
+                    } elseif ($tokenContent === ',') {
+                        $useAsContext = false;
+                        $useStatementIndex++;
+                        $infos[$infoIndex]['statements'][$useStatementIndex] = array('use' => null,
+                            'as' => null);
+                    }
+                }
+
+                // ANALYZE
+                if ($this->tokenType !== null) {
+                    if ($this->tokenType == T_AS) {
+                        $useAsContext = true;
+                        goto SCANNER_USE_CONTINUE;
+                    }
+
+                    if ($this->tokenType == T_NS_SEPARATOR || $this->tokenType == T_STRING) {
+                        if ($useAsContext == false) {
+                            $infos[$infoIndex]['statements'][$useStatementIndex]['use'] .= $tokenContent;
+                        } else {
+                            $infos[$infoIndex]['statements'][$useStatementIndex]['as'] = $tokenContent;
+                        }
+                    }
+                }
+
+                SCANNER_USE_CONTINUE:
+
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+                goto SCANNER_USE_TOP;
+
+                SCANNER_USE_END:
+
+                $MACRO_INFO_ADVANCE();
+                goto SCANNER_CONTINUE;
+            //goto no break needed
+
+            case T_INCLUDE:
+            case T_INCLUDE_ONCE:
+            case T_REQUIRE:
+            case T_REQUIRE_ONCE:
+
+                // Static for performance
+                static $includeTypes = array(
+                    T_INCLUDE => 'include',
+                    T_INCLUDE_ONCE => 'include_once',
+                    T_REQUIRE => 'require',
+                    T_REQUIRE_ONCE => 'require_once'
+                );
+
+                $infos[$infoIndex] = array(
+                    'type' => 'include',
+                    'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(),
+                    'tokenEnd' => null,
+                    'lineStart' => $tokens[$tokenIndex][2],
+                    'lineEnd' => null,
+                    'includeType' => $includeTypes[$tokens[$tokenIndex][0]],
+                    'path' => '',
+                );
+
+                // start processing with next token
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+
+                SCANNER_INCLUDE_TOP:
+
+                if ($this->tokenType === null && $tokenContent === ';') {
+                    goto SCANNER_INCLUDE_END;
+                }
+
+                $infos[$infoIndex]['path'] .= $tokenContent;
+
+                SCANNER_INCLUDE_CONTINUE:
+
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+                goto SCANNER_INCLUDE_TOP;
+
+                SCANNER_INCLUDE_END:
+
+                $MACRO_INFO_ADVANCE();
+                goto SCANNER_CONTINUE;
+            //goto no break needed
+
+            case T_FUNCTION:
+            case T_FINAL:
+            case T_ABSTRACT:
+            case T_CLASS:
+            case T_INTERFACE:
+            case T_TRAIT:
+
+                $infos[$infoIndex] = array(
+                    'type' => ($this->tokenType === T_FUNCTION) ? 'function' : 'class',
+                    'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(),
+                    'tokenEnd' => null,
+                    'lineStart' => $tokens[$tokenIndex][2],
+                    'lineEnd' => null,
+                    'namespace' => $namespace,
+                    'uses' => $this->getUsesNoScan($namespace),
+                    'name' => null,
+                    'shortName' => null,
+                );
+
+                $classBraceCount = 0;
+
+                // start processing with current token
+
+                SCANNER_CLASS_TOP:
+
+                // process the name
+                if ($infos[$infoIndex]['shortName'] == ''
+                    && (($this->tokenType === T_CLASS || $this->tokenType === T_INTERFACE || $this->tokenType === T_TRAIT) && $infos[$infoIndex]['type'] === 'class'
+                        || ($this->tokenType === T_FUNCTION && $infos[$infoIndex]['type'] === 'function'))
+                ) {
+                    $infos[$infoIndex]['shortName'] = $tokens[$tokenIndex + 2][1];
+                    $infos[$infoIndex]['name'] = (($namespace !== null) ? $namespace . '\\' : '') . $infos[$infoIndex]['shortName'];
+                }
+
+                if ($this->tokenType === null) {
+                    if ($tokenContent == '{') {
+                        $classBraceCount++;
+                    }
+                    if ($tokenContent == '}') {
+                        $classBraceCount--;
+                        if ($classBraceCount === 0) {
+                            goto SCANNER_CLASS_END;
+                        }
+                    }
+                }
+
+                SCANNER_CLASS_CONTINUE:
+
+                if ($MACRO_TOKEN_ADVANCE() === false) {
+                    goto SCANNER_END;
+                }
+                goto SCANNER_CLASS_TOP;
+
+                SCANNER_CLASS_END:
+
+                $MACRO_INFO_ADVANCE();
+                goto SCANNER_CONTINUE;
+
+        }
+
+        SCANNER_CONTINUE:
+
+        if ($MACRO_TOKEN_ADVANCE() === false) {
+            goto SCANNER_END;
+        }
+        goto SCANNER_TOP;
+
+        SCANNER_END:
+
+        /**
+         * END FINITE STATE MACHINE FOR SCANNING TOKENS
+         */
+
+        $this->isScanned = true;
+    }
+}
\ No newline at end of file
diff --git a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
index 135e03ae69b800d593bf6c0592f7454c7b9f1da2..2d98bc58f789ad4b8476fa057e615c27d7093253 100644
--- a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
+++ b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php
@@ -123,16 +123,20 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface
                 /** @var \Magento\Framework\App\State $adminAppState */
                 $adminAppState = $objectManager->get('Magento\Framework\App\State');
                 $adminAppState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMIN);
+                /** @var \Magento\Backend\Model\Session\AdminConfig $sessionConfig */
+                $sessionConfig = $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class);
+                $cookiePath = $this->getSetupCookiePath($objectManager);
+                $sessionConfig->setCookiePath($cookiePath);
                 /** @var \Magento\Backend\Model\Auth\Session $adminSession */
                 $adminSession = $objectManager->create(
                     \Magento\Backend\Model\Auth\Session::class,
                     [
-                        'sessionConfig' => $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class),
+                        'sessionConfig' => $sessionConfig,
                         'appState' => $adminAppState
                     ]
                 );
                 if (!$objectManager->get(\Magento\Backend\Model\Auth::class)->isLoggedIn()) {
-                    $adminSession->expireSessionCookie();
+                    $adminSession->destroy();
                     $response = $event->getResponse();
                     $response->getHeaders()->addHeaderLine('Location', 'index.php/session/unlogin');
                     $response->setStatusCode(302);
@@ -145,6 +149,25 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface
         return false;
     }
 
+    /**
+     * Get cookie path
+     *
+     * @param \Magento\Framework\ObjectManagerInterface $objectManager
+     * @return string
+     */
+    private function getSetupCookiePath(\Magento\Framework\ObjectManagerInterface $objectManager)
+    {
+        /** @var \Magento\Backend\App\BackendAppList $backendAppList */
+        $backendAppList = $objectManager->get(\Magento\Backend\App\BackendAppList::class);
+        $backendApp = $backendAppList->getBackendApp('setup');
+        /** @var \Magento\Backend\Model\UrlFactory $backendUrlFactory */
+        $backendUrlFactory = $objectManager->get(\Magento\Backend\Model\UrlFactory::class);
+        $baseUrl = parse_url($backendUrlFactory->create()->getBaseUrl(), PHP_URL_PATH);
+        $baseUrl = \Magento\Framework\App\Request\Http::getUrlNoScript($baseUrl);
+        $cookiePath = $baseUrl . $backendApp->getCookiePath();
+        return $cookiePath;
+    }
+
     /**
      * {@inheritdoc}
      */