diff --git a/app/code/Magento/Catalog/etc/config.xml b/app/code/Magento/Catalog/etc/config.xml
index 9d4433c045425e2902dbc8b60c43ba01fcbeba7a..75518179376fbb2d52d8dcb94379d29c41fb51d2 100644
--- a/app/code/Magento/Catalog/etc/config.xml
+++ b/app/code/Magento/Catalog/etc/config.xml
@@ -51,6 +51,7 @@
         <system>
             <media_storage_configuration>
                 <allowed_resources>
+                    <tmp_images_folder>tmp</tmp_images_folder>
                     <catalog_images_folder>catalog</catalog_images_folder>
                     <product_custom_options_fodler>custom_options</product_custom_options_fodler>
                 </allowed_resources>
diff --git a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
index e459e07201fe3e98b61dc4af7adbcaf777f0a78b..2f5c1181ea10d44c4a4e99294dac2ee068822387 100644
--- a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
+++ b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js
@@ -8,7 +8,8 @@ define([
     'ko',
     'Magento_Customer/js/section-config',
     'jquery/jquery-storageapi',
-    'jquery/jquery-cookie'
+    'jquery/jquery.cookie'
+
 ], function ($, _, ko, sectionConfig) {
     'use strict';
 
diff --git a/app/code/Magento/MediaStorage/App/Media.php b/app/code/Magento/MediaStorage/App/Media.php
index f7c60c1a4eef7c5bf3f6c0fe21232b96c3118bc8..59754755a89d55ca235ccb60d430ddf3b874122f 100644
--- a/app/code/Magento/MediaStorage/App/Media.php
+++ b/app/code/Magento/MediaStorage/App/Media.php
@@ -7,149 +7,131 @@
  */
 namespace Magento\MediaStorage\App;
 
-use Magento\MediaStorage\Model\File\Storage\Request;
+use Magento\Framework\Filesystem;
+use Magento\MediaStorage\Model\File\Storage\ConfigFactory;
 use Magento\MediaStorage\Model\File\Storage\Response;
 use Magento\Framework\App;
 use Magento\Framework\App\Filesystem\DirectoryList;
 use Magento\Framework\AppInterface;
-use Magento\Framework\ObjectManagerInterface;
+use Magento\MediaStorage\Model\File\Storage\SynchronizationFactory;
 
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
 class Media implements AppInterface
 {
-    /**
-     * @var \Magento\Framework\ObjectManagerInterface
-     */
-    protected $_objectManager;
-
-    /**
-     * @var \Magento\MediaStorage\Model\File\Storage\Request
-     */
-    protected $_request;
-
     /**
      * Authorization function
      *
      * @var \Closure
      */
-    protected $_isAllowed;
+    private $isAllowed;
 
     /**
      * Media directory path
      *
      * @var string
      */
-    protected $_mediaDirectory;
+    private $mediaDirectoryPath;
 
     /**
      * Configuration cache file path
      *
      * @var string
      */
-    protected $_configCacheFile;
+    private $configCacheFile;
 
     /**
      * Requested file name relative to working directory
      *
      * @var string
      */
-    protected $_relativeFileName;
+    private $relativeFileName;
 
     /**
-     * Working directory
-     *
-     * @var string
+     * @var Response
      */
-    protected $_workingDirectory;
+    private $response;
 
     /**
-     * @var \Magento\MediaStorage\Model\File\Storage\Response
+     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
      */
-    protected $_response;
+    private $directory;
 
     /**
-     * @var \Magento\Framework\Filesystem $filesystem
+     * @var ConfigFactory
      */
-    protected $filesystem;
+    private $configFactory;
 
     /**
-     * @var \Magento\Framework\Filesystem\Directory\Read $directory
+     * @var SynchronizationFactory
      */
-    protected $directory;
+    private $syncFactory;
 
     /**
-     * @param ObjectManagerInterface $objectManager
-     * @param Request $request
+     * @param ConfigFactory $configFactory
+     * @param SynchronizationFactory $syncFactory
      * @param Response $response
      * @param \Closure $isAllowed
-     * @param string $workingDirectory
      * @param string $mediaDirectory
      * @param string $configCacheFile
      * @param string $relativeFileName
-     * @param \Magento\Framework\Filesystem $filesystem
+     * @param Filesystem $filesystem
      */
     public function __construct(
-        ObjectManagerInterface $objectManager,
-        Request $request,
+        ConfigFactory $configFactory,
+        SynchronizationFactory $syncFactory,
         Response $response,
         \Closure $isAllowed,
-        $workingDirectory,
         $mediaDirectory,
         $configCacheFile,
         $relativeFileName,
-        \Magento\Framework\Filesystem $filesystem
+        Filesystem $filesystem
     ) {
-        $this->_objectManager = $objectManager;
-        $this->_request = $request;
-        $this->_response = $response;
-        $this->_isAllowed = $isAllowed;
-        $this->_workingDirectory = $workingDirectory;
-        $this->_mediaDirectory = $mediaDirectory;
-        $this->_configCacheFile = $configCacheFile;
-        $this->_relativeFileName = $relativeFileName;
-        $this->filesystem = $filesystem;
-        $this->directory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA);
+        $this->response = $response;
+        $this->isAllowed = $isAllowed;
+        $this->directory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
+        $mediaDirectory = trim($mediaDirectory);
+        if (!empty($mediaDirectory)) {
+            $this->mediaDirectoryPath = str_replace('\\', '/', realpath($mediaDirectory));
+        }
+        $this->configCacheFile = $configCacheFile;
+        $this->relativeFileName = $relativeFileName;
+        $this->configFactory = $configFactory;
+        $this->syncFactory = $syncFactory;
     }
 
     /**
      * Run application
      *
-     * @return \Magento\Framework\App\ResponseInterface
+     * @return Response
      * @throws \LogicException
      */
     public function launch()
     {
-        if (!$this->_mediaDirectory) {
-            $config = $this->_objectManager->create(
-                'Magento\MediaStorage\Model\File\Storage\Config',
-                ['cacheFile' => $this->_configCacheFile]
-            );
+        if ($this->mediaDirectoryPath !== $this->directory->getAbsolutePath()) {
+            // Path to media directory changed or absent - update the config
+            /** @var \Magento\MediaStorage\Model\File\Storage\Config $config */
+            $config = $this->configFactory->create(['cacheFile' => $this->configCacheFile]);
             $config->save();
-            $this->_mediaDirectory = str_replace($this->_workingDirectory, '', $config->getMediaDirectory());
+            $this->mediaDirectoryPath = $config->getMediaDirectory();
             $allowedResources = $config->getAllowedResources();
-            $this->_relativeFileName = str_replace(
-                $this->_mediaDirectory . '/',
-                '',
-                $this->_request->getPathInfo()
-            );
-            $isAllowed = $this->_isAllowed;
-            if (!$isAllowed($this->_relativeFileName, $allowedResources)) {
+            $isAllowed = $this->isAllowed;
+            if (!$isAllowed($this->relativeFileName, $allowedResources)) {
                 throw new \LogicException('The specified path is not allowed.');
             }
         }
 
-        if (0 !== stripos($this->_request->getPathInfo(), $this->_mediaDirectory . '/')) {
-            throw new \LogicException('The specified path is not within media directory.');
-        }
-
-        $sync = $this->_objectManager->get('Magento\MediaStorage\Model\File\Storage\Synchronization');
-        $sync->synchronize($this->_relativeFileName, $this->_request->getFilePath());
+        /** @var \Magento\MediaStorage\Model\File\Storage\Synchronization $sync */
+        $sync = $this->syncFactory->create(['directory' => $this->directory]);
+        $sync->synchronize($this->relativeFileName);
 
-        if ($this->directory->isReadable($this->directory->getRelativePath($this->_request->getFilePath()))) {
-            $this->_response->setFilePath($this->_request->getFilePath());
+        if ($this->directory->isReadable($this->relativeFileName)) {
+            $this->response->setFilePath($this->directory->getAbsolutePath($this->relativeFileName));
         } else {
-            $this->_response->setHttpResponseCode(404);
+            $this->response->setHttpResponseCode(404);
         }
-        return $this->_response;
+        return $this->response;
     }
 
     /**
@@ -157,8 +139,12 @@ class Media implements AppInterface
      */
     public function catchException(App\Bootstrap $bootstrap, \Exception $exception)
     {
-        $this->_response->setHttpResponseCode(404);
-        $this->_response->sendHeaders();
+        $this->response->setHttpResponseCode(404);
+        if ($bootstrap->isDeveloperMode()) {
+            $this->response->setHeader('Content-Type', 'text/plain');
+            $this->response->setBody($exception->getMessage() . "\n" . $exception->getTraceAsString());
+        }
+        $this->response->sendResponse();
         return true;
     }
 }
diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Config.php b/app/code/Magento/MediaStorage/Model/File/Storage/Config.php
index 404434584903b317a9d6d6958e6449b0ade8e8b0..e57770297f829a551cd601c72fb4558e1eb3717c 100644
--- a/app/code/Magento/MediaStorage/Model/File/Storage/Config.php
+++ b/app/code/Magento/MediaStorage/Model/File/Storage/Config.php
@@ -31,7 +31,7 @@ class Config
      *
      * @var DirectoryWrite
      */
-    protected $pubDirectory;
+    protected $rootDirectory;
 
     /**
      * @param \Magento\MediaStorage\Model\File\Storage $storage
@@ -44,7 +44,7 @@ class Config
         $cacheFile
     ) {
         $this->config = $storage->getScriptConfig();
-        $this->pubDirectory = $filesystem->getDirectoryWrite(DirectoryList::PUB);
+        $this->rootDirectory = $filesystem->getDirectoryWrite(DirectoryList::ROOT);
         $this->cacheFilePath = $cacheFile;
     }
 
@@ -76,7 +76,7 @@ class Config
     public function save()
     {
         /** @var Write $file */
-        $file = $this->pubDirectory->openFile($this->pubDirectory->getRelativePath($this->cacheFilePath), 'w');
+        $file = $this->rootDirectory->openFile($this->rootDirectory->getRelativePath($this->cacheFilePath), 'w');
         try {
             $file->lock();
             $file->write(json_encode($this->config));
diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php
index ff1a6db2e212ed1fbd5574145876d3c611b152a6..ad57bd14addd33d119fe4d6b97ae42bf164a5ace 100644
--- a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php
+++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php
@@ -11,11 +11,9 @@ namespace Magento\MediaStorage\Model\File\Storage\Database;
 abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel
 {
     /**
-     * Store media base directory path
-     *
-     * @var string
+     * Default connection
      */
-    protected $_mediaBaseDirectory = null;
+    const CONNECTION_DEFAULT = 'default_setup';
 
     /**
      * Core file storage database
@@ -36,6 +34,13 @@ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel
      */
     protected $_configuration;
 
+    /**
+     * Connection name
+     *
+     * @var string
+     */
+    private $connectionName = self::CONNECTION_DEFAULT;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -81,7 +86,7 @@ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel
                 'default'
             );
         if (empty($connectionName)) {
-            $connectionName = 'default_setup';
+            $connectionName = self::CONNECTION_DEFAULT;
         }
         return $connectionName;
     }
@@ -120,10 +125,20 @@ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel
     public function setConnectionName($connectionName)
     {
         if (!empty($connectionName)) {
-            $this->setData('connection_name', $connectionName);
-            $this->_getResource()->setConnectionName($connectionName);
+            $this->connectionName = $connectionName;
+            $this->_getResource()->setConnectionName($this->connectionName);
         }
 
         return $this;
     }
+
+    /**
+     * Get connection name
+     *
+     * @return null|string
+     */
+    public function getConnectionName()
+    {
+        return $this->connectionName;
+    }
 }
diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Request.php b/app/code/Magento/MediaStorage/Model/File/Storage/Request.php
index 890d2f8ad16af6fc12125c011fa0a0d672e8fc70..72bb21ba7330581275f076a1ca377500a1414e94 100644
--- a/app/code/Magento/MediaStorage/Model/File/Storage/Request.php
+++ b/app/code/Magento/MediaStorage/Model/File/Storage/Request.php
@@ -14,26 +14,14 @@ class Request
      *
      * @var string
      */
-    protected $_pathInfo;
+    private $pathInfo;
 
     /**
-     * Requested file path
-     *
-     * @var string
-     */
-    protected $_filePath;
-
-    /**
-     * @param string $workingDir
      * @param HttpRequest $request
      */
-    public function __construct($workingDir, HttpRequest $request = null)
+    public function __construct(HttpRequest $request)
     {
-        $request = $request ?: new HttpRequest(
-            new \Magento\Framework\Stdlib\Cookie\PhpCookieReader()
-        );
-        $this->_pathInfo = str_replace('..', '', ltrim($request->getPathInfo(), '/'));
-        $this->_filePath = $workingDir . '/' . $this->_pathInfo;
+        $this->pathInfo = str_replace('..', '', ltrim($request->getPathInfo(), '/'));
     }
 
     /**
@@ -43,16 +31,6 @@ class Request
      */
     public function getPathInfo()
     {
-        return $this->_pathInfo;
-    }
-
-    /**
-     * Retrieve file path
-     *
-     * @return string
-     */
-    public function getFilePath()
-    {
-        return $this->_filePath;
+        return $this->pathInfo;
     }
 }
diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Synchronization.php b/app/code/Magento/MediaStorage/Model/File/Storage/Synchronization.php
index 88a72ad5c6e6bfb12f5d9165fa7860ff283b4e44..97ef3597b2d5acd175a639dff3022fa393253f39 100644
--- a/app/code/Magento/MediaStorage/Model/File/Storage/Synchronization.php
+++ b/app/code/Magento/MediaStorage/Model/File/Storage/Synchronization.php
@@ -5,7 +5,6 @@
  */
 namespace Magento\MediaStorage\Model\File\Storage;
 
-use Magento\Framework\App\Filesystem\DirectoryList;
 use Magento\Framework\Filesystem\Directory\WriteInterface as DirectoryWrite;
 use Magento\Framework\Filesystem\File\Write;
 use Magento\Framework\Exception\FileSystemException;
@@ -27,29 +26,28 @@ class Synchronization
      *
      * @var DirectoryWrite
      */
-    protected $pubDirectory;
+    protected $mediaDirectory;
 
     /**
      * @param \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageFactory
-     * @param \Magento\Framework\Filesystem $filesystem
+     * @param DirectoryWrite $directory
      */
     public function __construct(
         \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageFactory,
-        \Magento\Framework\Filesystem $filesystem
+        DirectoryWrite $directory
     ) {
         $this->storageFactory = $storageFactory;
-        $this->pubDirectory = $filesystem->getDirectoryWrite(DirectoryList::PUB);
+        $this->mediaDirectory = $directory;
     }
 
     /**
      * Synchronize file
      *
      * @param string $relativeFileName
-     * @param string $filePath
      * @return void
      * @throws \LogicException
      */
-    public function synchronize($relativeFileName, $filePath)
+    public function synchronize($relativeFileName)
     {
         /** @var $storage \Magento\MediaStorage\Model\File\Storage\Database */
         $storage = $this->storageFactory->create();
@@ -59,7 +57,7 @@ class Synchronization
         }
         if ($storage->getId()) {
             /** @var Write $file */
-            $file = $this->pubDirectory->openFile($this->pubDirectory->getRelativePath($filePath), 'w');
+            $file = $this->mediaDirectory->openFile($relativeFileName, 'w');
             try {
                 $file->lock();
                 $file->write($storage->getContent());
diff --git a/app/code/Magento/MediaStorage/Test/Unit/App/MediaTest.php b/app/code/Magento/MediaStorage/Test/Unit/App/MediaTest.php
index 78a2ae48f753d6bde57aedcdc6f1153a34686dcf..8e33723f8de6564345d1d9134886ab9d872d5f9b 100644
--- a/app/code/Magento/MediaStorage/Test/Unit/App/MediaTest.php
+++ b/app/code/Magento/MediaStorage/Test/Unit/App/MediaTest.php
@@ -9,138 +9,139 @@ use Magento\Framework\App\Filesystem\DirectoryList;
 
 class MediaTest extends \PHPUnit_Framework_TestCase
 {
+    const MEDIA_DIRECTORY = 'mediaDirectory';
+    const RELATIVE_FILE_PATH = 'test/file.png';
+    const CACHE_FILE_PATH = 'var';
+
     /**
      * @var \Magento\MediaStorage\App\Media
      */
-    protected $_model;
+    private $model;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\MediaStorage\Model\File\Storage\ConfigFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_objectManagerMock;
+    private $configFactoryMock;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\MediaStorage\Model\File\Storage\SynchronizationFactory|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_requestMock;
+    private $syncFactoryMock;
 
     /**
      * @var callable
      */
-    protected $_closure;
+    private $closure;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_configMock;
+    private $configMock;
 
     /**
      * @var \PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_sync;
-
-    /**
-     * @var string
-     */
-    protected $_mediaDirectory = 'mediaDirectory';
+    private $sync;
 
     /**
-     * @var \PHPUnit_Framework_MockObject_MockObject
+     * @var \Magento\MediaStorage\Model\File\Storage\Response|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $_responseMock;
+    private $responseMock;
 
     /**
      * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $filesystemMock;
+    private $filesystemMock;
 
     /**
      * @var \Magento\Framework\Filesystem\Directory\Read|\PHPUnit_Framework_MockObject_MockObject
      */
-    protected $directoryReadMock;
+    private $directoryMock;
 
     protected function setUp()
     {
-        $this->_requestMock = $this->getMock('Magento\MediaStorage\Model\File\Storage\Request', [], [], '', false);
-        $this->_closure = function () {
+        $this->closure = function () {
             return true;
         };
-        $this->_objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface');
-        $this->_configMock = $this->getMock('Magento\MediaStorage\Model\File\Storage\Config', [], [], '', false);
-        $this->_sync = $this->getMock('Magento\MediaStorage\Model\File\Storage\Synchronization', [], [], '', false);
-
-        $this->filesystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
-        $this->directoryReadMock = $this->getMock(
-            'Magento\Framework\Filesystem\Directory\Read',
-            [],
+        $this->configMock = $this->getMock('Magento\MediaStorage\Model\File\Storage\Config', [], [], '', false);
+        $this->sync = $this->getMock('Magento\MediaStorage\Model\File\Storage\Synchronization', [], [], '', false);
+        $this->configFactoryMock = $this->getMock(
+            'Magento\MediaStorage\Model\File\Storage\ConfigFactory',
+            ['create'],
             [],
             '',
             false
         );
-
-        $this->filesystemMock->expects(
-            $this->any()
-        )->method(
-            'getDirectoryRead'
-        )->with(
-            DirectoryList::MEDIA
-        )->will(
-            $this->returnValue($this->directoryReadMock)
+        $this->configFactoryMock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->configMock));
+        $this->syncFactoryMock = $this->getMock(
+            'Magento\MediaStorage\Model\File\Storage\SynchronizationFactory',
+            ['create'],
+            [],
+            '',
+            false
         );
+        $this->syncFactoryMock->expects($this->any())
+            ->method('create')
+            ->will($this->returnValue($this->sync));
 
-        $this->_responseMock = $this->getMock('Magento\MediaStorage\Model\File\Storage\Response', [], [], '', false);
-
-        $map = [
-            ['Magento\MediaStorage\Model\File\Storage\Request', $this->_requestMock],
-            ['Magento\MediaStorage\Model\File\Storage\Synchronization', $this->_sync],
-        ];
-        $this->_model = new \Magento\MediaStorage\App\Media(
-            $this->_objectManagerMock,
-            $this->_requestMock,
-            $this->_responseMock,
-            $this->_closure,
-            'baseDir',
-            'mediaDirectory',
-            'var',
-            'params',
+        $this->filesystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
+        $this->directoryMock = $this->getMockForAbstractClass('Magento\Framework\Filesystem\Directory\WriteInterface');
+
+        $this->filesystemMock->expects($this->any())
+            ->method('getDirectoryWrite')
+            ->with(DirectoryList::MEDIA)
+            ->will($this->returnValue($this->directoryMock));
+
+        $this->responseMock = $this->getMock('Magento\MediaStorage\Model\File\Storage\Response', [], [], '', false);
+
+        $this->model = new \Magento\MediaStorage\App\Media(
+            $this->configFactoryMock,
+            $this->syncFactoryMock,
+            $this->responseMock,
+            $this->closure,
+            self::MEDIA_DIRECTORY,
+            self::CACHE_FILE_PATH,
+            self::RELATIVE_FILE_PATH,
             $this->filesystemMock
         );
-        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnValueMap($map));
     }
 
     protected function tearDown()
     {
-        unset($this->_model);
+        unset($this->model);
     }
 
-    /**
-     * @expectedException \LogicException
-     * @expectedExceptionMessage The specified path is not within media directory.
-     */
     public function testProcessRequestCreatesConfigFileMediaDirectoryIsNotProvided()
     {
-        $this->_model = new \Magento\MediaStorage\App\Media(
-            $this->_objectManagerMock,
-            $this->_requestMock,
-            $this->_responseMock,
-            $this->_closure,
-            'baseDir',
+        $this->model = new \Magento\MediaStorage\App\Media(
+            $this->configFactoryMock,
+            $this->syncFactoryMock,
+            $this->responseMock,
+            $this->closure,
             false,
-            'var',
-            'params',
+            self::CACHE_FILE_PATH,
+            self::RELATIVE_FILE_PATH,
             $this->filesystemMock
         );
-        $this->_objectManagerMock->expects(
-            $this->once()
-        )->method(
-            'create'
-        )->with(
-            'Magento\MediaStorage\Model\File\Storage\Config'
-        )->will(
-            $this->returnValue($this->_configMock)
-        );
-        $this->_configMock->expects($this->once())->method('save');
-        $this->_model->launch();
+        $filePath = '/absolute/path/to/test/file.png';
+        $this->directoryMock->expects($this->any())
+            ->method('getAbsolutePath')
+            ->will($this->returnValueMap(
+                [
+                    [null, self::MEDIA_DIRECTORY],
+                    [self::RELATIVE_FILE_PATH, $filePath],
+                ]
+            ));
+        $this->configMock->expects($this->once())->method('save');
+        $this->sync->expects($this->once())->method('synchronize')->with(self::RELATIVE_FILE_PATH);
+        $this->directoryMock->expects($this->once())
+            ->method('isReadable')
+            ->with(self::RELATIVE_FILE_PATH)
+            ->will($this->returnValue(true));
+        $this->responseMock->expects($this->once())->method('setFilePath')->with($filePath);
+        $this->model->launch();
     }
 
     /**
@@ -149,101 +150,90 @@ class MediaTest extends \PHPUnit_Framework_TestCase
      */
     public function testProcessRequestReturnsNotFoundResponseIfResourceIsNotAllowed()
     {
-        $this->_closure = function () {
+        $this->closure = function () {
             return false;
         };
-        $this->_model = new \Magento\MediaStorage\App\Media(
-            $this->_objectManagerMock,
-            $this->_requestMock,
-            $this->_responseMock,
-            $this->_closure,
-            'baseDir',
+        $this->model = new \Magento\MediaStorage\App\Media(
+            $this->configFactoryMock,
+            $this->syncFactoryMock,
+            $this->responseMock,
+            $this->closure,
             false,
-            'var',
-            'params',
+            self::CACHE_FILE_PATH,
+            self::RELATIVE_FILE_PATH,
             $this->filesystemMock
         );
-        $this->_requestMock->expects($this->once())->method('getPathInfo');
-        $this->_objectManagerMock->expects(
-            $this->once()
-        )->method(
-            'create'
-        )->with(
-            'Magento\MediaStorage\Model\File\Storage\Config'
-        )->will(
-            $this->returnValue($this->_configMock)
-        );
-        $this->_configMock->expects($this->once())->method('getAllowedResources')->will($this->returnValue(false));
-        $this->_model->launch();
+        $this->directoryMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->with()
+            ->will($this->returnValue(self::MEDIA_DIRECTORY));
+        $this->configMock->expects($this->once())->method('getAllowedResources')->will($this->returnValue(false));
+        $this->model->launch();
     }
 
-    /**
-     * @expectedException \LogicException
-     * @expectedExceptionMessage The specified path is not within media directory.
-     */
-    public function testProcessRequestReturnsNotFoundIfFileIsNotAllowed()
+    public function testProcessRequestReturnsFileIfItsProperlySynchronized()
     {
-        $this->_configMock->expects($this->never())->method('save');
-        $this->_requestMock->expects($this->once())->method('getPathInfo');
-        $this->_requestMock->expects($this->never())->method('getFilePath');
-        $this->_model->launch();
+        $filePath = '/absolute/path/to/test/file.png';
+        $this->sync->expects($this->once())->method('synchronize')->with(self::RELATIVE_FILE_PATH);
+        $this->directoryMock->expects($this->once())
+            ->method('isReadable')
+            ->with(self::RELATIVE_FILE_PATH)
+            ->will($this->returnValue(true));
+        $this->directoryMock->expects($this->any())
+            ->method('getAbsolutePath')
+            ->will($this->returnValueMap(
+                [
+                    [null, self::MEDIA_DIRECTORY],
+                    [self::RELATIVE_FILE_PATH, $filePath],
+                ]
+            ));
+        $this->responseMock->expects($this->once())->method('setFilePath')->with($filePath);
+        $this->assertSame($this->responseMock, $this->model->launch());
     }
 
-    public function testProcessRequestReturnsFileIfItsProperlySynchronized()
+    public function testProcessRequestReturnsNotFoundIfFileIsNotSynchronized()
     {
-        $relativeFilePath = '_files';
-        $filePath = str_replace('\\', '/', __DIR__ . '/' . $relativeFilePath);
-        $this->_requestMock->expects(
-            $this->any()
-        )->method(
-            'getPathInfo'
-        )->will(
-            $this->returnValue($this->_mediaDirectory . '/')
-        );
-        $this->_sync->expects($this->once())->method('synchronize');
-        $this->_requestMock->expects($this->any())->method('getFilePath')->will($this->returnValue($filePath));
-
-        $this->directoryReadMock->expects(
-            $this->once()
-        )->method(
-            'getRelativePath'
-        )->with(
-            $filePath
-        )->will(
-            $this->returnValue($relativeFilePath)
-        );
+        $this->sync->expects($this->once())->method('synchronize')->with(self::RELATIVE_FILE_PATH);
+        $this->directoryMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->with()
+            ->will($this->returnValue(self::MEDIA_DIRECTORY));
+        $this->directoryMock->expects($this->once())
+            ->method('isReadable')
+            ->with(self::RELATIVE_FILE_PATH)
+            ->will($this->returnValue(false));
+        $this->responseMock->expects($this->once())->method('setHttpResponseCode')->with(404);
+        $this->assertSame($this->responseMock, $this->model->launch());
+    }
 
-        $this->directoryReadMock->expects(
-            $this->once()
-        )->method(
-            'isReadable'
-        )->with(
-            $relativeFilePath
-        )->will(
-            $this->returnValue(true)
-        );
-        $this->_responseMock->expects($this->once())->method('setFilePath')->with($filePath);
-        $this->assertSame($this->_responseMock, $this->_model->launch());
+    /**
+     * @param bool $isDeveloper
+     * @param int $setBodyCalls
+     *
+     * @dataProvider catchExceptionDataProvider
+     */
+    public function testCatchException($isDeveloper, $setBodyCalls)
+    {
+        $bootstrap = $this->getMock('Magento\Framework\App\Bootstrap', [], [], '', false);
+        $exception = $this->getMock('Exception', [], [], '', false);
+        $this->responseMock->expects($this->once())
+            ->method('setHttpResponseCode')
+            ->with(404);
+        $bootstrap->expects($this->once())
+            ->method('isDeveloperMode')
+            ->will($this->returnValue($isDeveloper));
+        $this->responseMock->expects($this->exactly($setBodyCalls))
+            ->method('setBody');
+        $this->responseMock->expects($this->once())
+            ->method('sendResponse');
+        $this->model->catchException($bootstrap, $exception);
     }
 
-    public function testProcessRequestReturnsNotFoundIfFileIsNotSynchronized()
+    public function catchExceptionDataProvider()
     {
-        $this->_requestMock->expects(
-            $this->any()
-        )->method(
-            'getPathInfo'
-        )->will(
-            $this->returnValue($this->_mediaDirectory . '/')
-        );
-        $this->_sync->expects($this->once())->method('synchronize');
-        $this->_requestMock->expects(
-            $this->any()
-        )->method(
-            'getFilePath'
-        )->will(
-            $this->returnValue('non_existing_file_name')
-        );
-        $this->_responseMock->expects($this->once())->method('setHttpResponseCode')->with(404);
-        $this->assertSame($this->_responseMock, $this->_model->launch());
+        return [
+            'default mode' => [false, 0],
+            'developer mode' => [true, 1],
+        ];
     }
 }
diff --git a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/ConfigTest.php b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/ConfigTest.php
index 77da8d96f340fca9e03f35a8f1935175ab8073b0..33e9215f5684a93c4f63407652c9f7acd3c17f48 100644
--- a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/ConfigTest.php
+++ b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/ConfigTest.php
@@ -50,7 +50,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
         )->method(
             'getDirectoryWrite'
         )->with(
-            DirectoryList::PUB
+            DirectoryList::ROOT
         )->will(
             $this->returnValue($directory)
         );
diff --git a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/Directory/DatabaseTest.php b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/Directory/DatabaseTest.php
index 20478318e093800ef1a163024c293ac1a5f1e53d..f9f55588c98cbf5b19111277115327e5f861c9ab 100644
--- a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/Directory/DatabaseTest.php
+++ b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/Directory/DatabaseTest.php
@@ -192,4 +192,13 @@ class DatabaseTest extends \PHPUnit_Framework_TestCase
 
         $this->directoryDatabase->importDirectories('not an array');
     }
+
+    public function testSetGetConnectionName()
+    {
+        $this->assertSame($this->customConnectionName, $this->directoryDatabase->getConnectionName());
+        $this->directoryDatabase->setConnectionName('test');
+        $this->assertSame('test', $this->directoryDatabase->getConnectionName());
+        $this->directoryDatabase->unsetData();
+        $this->assertSame('test', $this->directoryDatabase->getConnectionName());
+    }
 }
diff --git a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/RequestTest.php b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/RequestTest.php
index 8c4f374dce42643e2be185e0c9d1e9c2dc099718..8ae7c41dd901831b4a83a2c0940adfe122082fc4 100644
--- a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/RequestTest.php
+++ b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/RequestTest.php
@@ -17,11 +17,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
      */
     protected $_requestMock;
 
-    /**
-     * @var string
-     */
-    protected $_workingDir = '..var';
-
     /**
      * @var string
      */
@@ -32,7 +27,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
         $path = '..PathInfo';
         $this->_requestMock = $this->getMock('\Magento\Framework\App\Request\Http', [], [], '', false);
         $this->_requestMock->expects($this->once())->method('getPathInfo')->will($this->returnValue($path));
-        $this->_model = new \Magento\MediaStorage\Model\File\Storage\Request($this->_workingDir, $this->_requestMock);
+        $this->_model = new \Magento\MediaStorage\Model\File\Storage\Request($this->_requestMock);
     }
 
     protected function tearDown()
@@ -45,9 +40,4 @@ class RequestTest extends \PHPUnit_Framework_TestCase
     {
         $this->assertEquals($this->_pathInfo, $this->_model->getPathInfo());
     }
-
-    public function testGetFilePath()
-    {
-        $this->assertEquals($this->_workingDir . '/' . $this->_pathInfo, $this->_model->getFilePath());
-    }
 }
diff --git a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/SynchronizationTest.php b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/SynchronizationTest.php
index 8d43e4e281f70eefad2c1d7bbbf1439231157ca1..6d41dff21fab30113eed1860819e196a2762cf5b 100644
--- a/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/SynchronizationTest.php
+++ b/app/code/Magento/MediaStorage/Test/Unit/Model/File/Storage/SynchronizationTest.php
@@ -5,18 +5,12 @@
  */
 namespace Magento\MediaStorage\Test\Unit\Model\File\Storage;
 
-use Magento\Framework\App\Filesystem\DirectoryList;
-
 class SynchronizationTest extends \PHPUnit_Framework_TestCase
 {
-    /**
-     * Test fir synchronize method
-     */
     public function testSynchronize()
     {
         $content = 'content';
         $relativeFileName = 'config.xml';
-        $filePath = realpath(__DIR__ . '/_files/');
 
         $storageFactoryMock = $this->getMock(
             'Magento\MediaStorage\Model\File\Storage\DatabaseFactory',
@@ -49,33 +43,13 @@ class SynchronizationTest extends \PHPUnit_Framework_TestCase
         $file->expects($this->once())->method('write')->with($content);
         $file->expects($this->once())->method('unlock');
         $file->expects($this->once())->method('close');
-        $directory = $this->getMock(
-            'Magento\Framework\Filesystem\Direcoty\Write',
-            ['openFile', 'getRelativePath'],
-            [],
-            '',
-            false
-        );
-        $directory->expects($this->once())->method('getRelativePath')->will($this->returnArgument(0));
-        $directory->expects($this->once())->method('openFile')->with($filePath)->will($this->returnValue($file));
-        $filesystem = $this->getMock(
-            'Magento\Framework\Filesystem',
-            ['getDirectoryWrite'],
-            [],
-            '',
-            false
-        );
-        $filesystem->expects(
-            $this->once()
-        )->method(
-            'getDirectoryWrite'
-        )->with(
-            DirectoryList::PUB
-        )->will(
-            $this->returnValue($directory)
-        );
+        $directory = $this->getMockForAbstractClass('Magento\Framework\Filesystem\Directory\WriteInterface');
+        $directory->expects($this->once())
+            ->method('openFile')
+            ->with($relativeFileName)
+            ->will($this->returnValue($file));
 
-        $model = new \Magento\MediaStorage\Model\File\Storage\Synchronization($storageFactoryMock, $filesystem);
-        $model->synchronize($relativeFileName, $filePath);
+        $model = new \Magento\MediaStorage\Model\File\Storage\Synchronization($storageFactoryMock, $directory);
+        $model->synchronize($relativeFileName);
     }
 }
diff --git a/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php b/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
index 2f62bc394b3b3e7ccdd0926c90b84843a7e958c9..b2af6f7e45f13904192371fe3404fa5a4684e705 100644
--- a/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
+++ b/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
@@ -194,25 +194,24 @@ class ThemeUninstallCommand extends Command
      */
     protected function execute(InputInterface $input, OutputInterface $output)
     {
+        $messages = [];
         $themePaths = $input->getArgument(self::INPUT_KEY_THEMES);
-        $validationMessages = $this->validate($themePaths);
-        if (!empty($validationMessages)) {
-            $output->writeln($validationMessages);
-            return;
-        }
-        $isThemeInUseMessages = $this->themeValidator->validateIsThemeInUse($themePaths);
-        if (!empty($isThemeInUseMessages)) {
-            $output->writeln($isThemeInUseMessages);
-            return;
-        }
-        $childThemeCheckMessages = $this->checkChildTheme($themePaths);
-        if (!empty($childThemeCheckMessages)) {
-            $output->writeln($childThemeCheckMessages);
+        $messages = array_merge($messages, $this->validate($themePaths));
+        if (!empty($messages)) {
+            $output->writeln($messages);
             return;
         }
-        $dependencyMessages = $this->checkDependencies($themePaths);
-        if (!empty($dependencyMessages)) {
-            $output->writeln($dependencyMessages);
+        $messages = array_merge(
+            $messages,
+            $this->themeValidator->validateIsThemeInUse($themePaths),
+            $this->checkChildTheme($themePaths),
+            $this->checkDependencies($themePaths)
+        );
+        if (!empty($messages)) {
+            $output->writeln(
+                '<error>Unable to uninstall. Please resolve the following issues:</error>'
+                . PHP_EOL . implode(PHP_EOL, $messages)
+            );
             return;
         }
 
@@ -290,8 +289,8 @@ class ThemeUninstallCommand extends Command
         foreach ($dependencies as $package => $dependingPackages) {
             if (!empty($dependingPackages)) {
                 $messages[] =
-                    '<error>Cannot uninstall ' . $packageToPath[$package] .
-                    " because the following package(s) depend on it:</error>" .
+                    '<error>' . $packageToPath[$package] .
+                    " has the following dependent package(s):</error>" .
                     PHP_EOL . "\t<error>" . implode('</error>' . PHP_EOL . "\t<error>", $dependingPackages)
                     . "</error>";
             }
@@ -322,13 +321,13 @@ class ThemeUninstallCommand extends Command
         }
         if (!empty($themeHasVirtualChildren)) {
             $text = count($themeHasVirtualChildren) > 1 ? ' are parents of' : ' is a parent of';
-            $messages[] = '<error>Unable to uninstall. '
-                . implode(', ', $themeHasVirtualChildren) . $text . ' virtual theme</error>';
+            $messages[] = '<error>' . implode(', ', $themeHasVirtualChildren) . $text . ' virtual theme.'
+                . ' Parent themes cannot be uninstalled.</error>';
         }
         if (!empty($themeHasPhysicalChildren)) {
             $text = count($themeHasPhysicalChildren) > 1 ? ' are parents of' : ' is a parent of';
-            $messages[] = '<error>Unable to uninstall. '
-                . implode(', ', $themeHasPhysicalChildren) . $text . ' physical theme</error>';
+            $messages[] = '<error>' . implode(', ', $themeHasPhysicalChildren) . $text . ' physical theme.'
+                . ' Parent themes cannot be uninstalled.</error>';
         }
         return $messages;
     }
diff --git a/app/code/Magento/Theme/Model/ThemeValidator.php b/app/code/Magento/Theme/Model/ThemeValidator.php
index 6f8b0ddda264fec695f8a03d194eaed3fb6a5899..3923eeb644db6bd499dd332bb7ac4ddc49dfaae7 100644
--- a/app/code/Magento/Theme/Model/ThemeValidator.php
+++ b/app/code/Magento/Theme/Model/ThemeValidator.php
@@ -75,15 +75,15 @@ class ThemeValidator
         foreach ($configData as $row) {
             switch($row['scope']) {
                 case 'default':
-                    $messages[] = $themesById[$row['value']] . ' is in use in default config';
+                    $messages[] = '<error>' . $themesById[$row['value']] . ' is in use in default config' . '</error>';
                     break;
                 case ScopeInterface::SCOPE_WEBSITES:
-                    $messages[] = $themesById[$row['value']] . ' is in use in website '
-                        . $this->storeManager->getWebsite($row['scope_id'])->getName();
+                    $messages[] = '<error>' . $themesById[$row['value']] . ' is in use in website '
+                        . $this->storeManager->getWebsite($row['scope_id'])->getName() . '</error>';
                     break;
                 case ScopeInterface::SCOPE_STORES:
-                    $messages[] = $themesById[$row['value']] . ' is in use in store '
-                        . $this->storeManager->getStore($row['scope_id'])->getName();
+                    $messages[] = '<error>' . $themesById[$row['value']] . ' is in use in store '
+                        . $this->storeManager->getStore($row['scope_id'])->getName() . '</error>';
                     break;
             }
         }
diff --git a/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php b/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
index c8c8f92a1b6c0b218a217e1aa7897410559a72a5..c2a78ac55524248028d3789069270ba942863ca7 100644
--- a/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
@@ -250,6 +250,33 @@ class ThemeUninstallCommandTest extends \PHPUnit_Framework_TestCase
         $this->collection->expects($this->any())->method('getIterator')->willReturn(new \ArrayIterator([]));
     }
 
+    public function setupPassThemeInUseCheck()
+    {
+        $this->themeValidator->expects($this->once())->method('validateIsThemeInUse')->willReturn([]);
+    }
+
+    public function setupPassDependencyCheck()
+    {
+        $this->dependencyChecker->expects($this->once())->method('checkDependencies')->willReturn([]);
+    }
+
+    public function testExecuteFailedThemeInUseCheck()
+    {
+        $this->setUpPassValidation();
+        $this->setupPassChildThemeCheck();
+        $this->setupPassDependencyCheck();
+        $this->themeValidator
+            ->expects($this->once())
+            ->method('validateIsThemeInUse')
+            ->willReturn(['frontend/Magento/a is in use in default config']);
+        $this->tester->execute(['theme' => ['frontend/Magento/a']]);
+        $this->assertEquals(
+            'Unable to uninstall. Please resolve the following issues:' . PHP_EOL
+            . 'frontend/Magento/a is in use in default config' . PHP_EOL,
+            $this->tester->getDisplay()
+        );
+    }
+
     /**
      * @dataProvider executeFailedChildThemeCheckDataProvider
      * @param bool $hasVirtual
@@ -261,6 +288,8 @@ class ThemeUninstallCommandTest extends \PHPUnit_Framework_TestCase
     public function testExecuteFailedChildThemeCheck($hasVirtual, $hasPhysical, array $input, $expected)
     {
         $this->setUpPassValidation();
+        $this->setupPassThemeInUseCheck();
+        $this->setupPassDependencyCheck();
         $theme = $this->getMock('Magento\Theme\Model\Theme', [], [], '', false);
         $theme->expects($this->any())->method('hasChildThemes')->willReturn($hasVirtual);
         $parentThemeA = $this->getMock('Magento\Theme\Model\Theme', [], [], '', false);
@@ -282,10 +311,7 @@ class ThemeUninstallCommandTest extends \PHPUnit_Framework_TestCase
             ->method('getIterator')
             ->willReturn(new \ArrayIterator([$childThemeC, $childThemeD]));
         $this->tester->execute($input);
-        $this->assertContains(
-            $expected,
-            $this->tester->getDisplay()
-        );
+        $this->assertContains($expected, $this->tester->getDisplay());
     }
 
     /**
@@ -298,65 +324,65 @@ class ThemeUninstallCommandTest extends \PHPUnit_Framework_TestCase
                 true,
                 false,
                 ['theme' => ['frontend/Magento/a']],
-                'Unable to uninstall. frontend/Magento/a is a parent of virtual theme'
+                'Unable to uninstall. Please resolve the following issues:' . PHP_EOL
+                . 'frontend/Magento/a is a parent of virtual theme. Parent themes cannot be uninstalled.'
             ],
             [
                 true,
                 false,
                 ['theme' => ['frontend/Magento/a', 'frontend/Magento/b']],
-                'Unable to uninstall. frontend/Magento/a, frontend/Magento/b are parents of virtual theme'
+                'Unable to uninstall. Please resolve the following issues:' . PHP_EOL .
+                'frontend/Magento/a, frontend/Magento/b are parents of virtual theme.'
+                . ' Parent themes cannot be uninstalled.'
             ],
             [
                 false,
                 true,
                 ['theme' => ['frontend/Magento/a']],
-                'Unable to uninstall. frontend/Magento/a is a parent of physical theme'
+                'Unable to uninstall. Please resolve the following issues:' . PHP_EOL .
+                'frontend/Magento/a is a parent of physical theme. Parent themes cannot be uninstalled.'
             ],
             [
                 false,
                 true,
                 ['theme' => ['frontend/Magento/a', 'frontend/Magento/b']],
-                'Unable to uninstall. frontend/Magento/a, frontend/Magento/b are parents of physical theme'
+                'Unable to uninstall. Please resolve the following issues:' . PHP_EOL .
+                'frontend/Magento/a, frontend/Magento/b are parents of physical theme.'
+                . ' Parent themes cannot be uninstalled.'
             ],
             [
                 true,
                 true,
                 ['theme' => ['frontend/Magento/a']],
-                'Unable to uninstall. frontend/Magento/a is a parent of virtual theme' . PHP_EOL .
-                'Unable to uninstall. frontend/Magento/a is a parent of physical theme'
+                'Unable to uninstall. Please resolve the following issues:' . PHP_EOL .
+                'frontend/Magento/a is a parent of virtual theme. Parent themes cannot be uninstalled.' . PHP_EOL .
+                'frontend/Magento/a is a parent of physical theme. Parent themes cannot be uninstalled.'
             ],
             [
                 true,
                 true,
                 ['theme' => ['frontend/Magento/a', 'frontend/Magento/b']],
-                'Unable to uninstall. frontend/Magento/a, frontend/Magento/b are parents of virtual theme' . PHP_EOL .
-                'Unable to uninstall. frontend/Magento/a, frontend/Magento/b are parents of physical theme'
+                'frontend/Magento/a, frontend/Magento/b are parents of virtual theme.'
+                . ' Parent themes cannot be uninstalled.' . PHP_EOL .
+                'frontend/Magento/a, frontend/Magento/b are parents of physical theme.'
+                . ' Parent themes cannot be uninstalled.'
             ],
         ];
     }
 
-    public function testExecuteFailedThemeInUseCheck()
-    {
-        $this->setUpPassValidation();
-        $this->themeValidator
-            ->expects($this->once())
-            ->method('validateIsThemeInUse')
-            ->willReturn(['frontend/Magento/a is in use in default config']);
-        $this->tester->execute(['theme' => ['frontend/Magento/a']]);
-        $this->assertEquals('frontend/Magento/a is in use in default config' . PHP_EOL, $this->tester->getDisplay());
-    }
-
     public function testExecuteFailedDependencyCheck()
     {
         $this->setUpPassValidation();
+        $this->setupPassThemeInUseCheck();
         $this->setupPassChildThemeCheck();
         $this->dependencyChecker->expects($this->once())
             ->method('checkDependencies')
             ->willReturn(['magento/theme-a' => ['magento/theme-b', 'magento/theme-c']]);
         $this->tester->execute(['theme' => ['frontend/Magento/a']]);
         $this->assertContains(
-            'Cannot uninstall frontend/Magento/a because the following package(s) ' .
-            'depend on it:' . PHP_EOL . "\tmagento/theme-b" . PHP_EOL . "\tmagento/theme-c",
+            'Unable to uninstall. Please resolve the following issues:' . PHP_EOL .
+            'frontend/Magento/a has the following dependent package(s):'
+            . PHP_EOL . "\tmagento/theme-b" . PHP_EOL . "\tmagento/theme-c",
             $this->tester->getDisplay()
         );
     }
@@ -364,8 +390,9 @@ class ThemeUninstallCommandTest extends \PHPUnit_Framework_TestCase
     public function setUpExecute()
     {
         $this->setUpPassValidation();
+        $this->setupPassThemeInUseCheck();
         $this->setupPassChildThemeCheck();
-        $this->dependencyChecker->expects($this->once())->method('checkDependencies')->willReturn([]);
+        $this->setupPassDependencyCheck();
         $this->remove->expects($this->once())->method('remove');
         $this->cache->expects($this->once())->method('clean');
         $theme = $this->getMock('Magento\Theme\Model\Theme', [], [], '', false);
diff --git a/app/code/Magento/Theme/Test/Unit/Model/ThemeValidatorTest.php b/app/code/Magento/Theme/Test/Unit/Model/ThemeValidatorTest.php
index d6fc5f272f5315d71f74bbb896e187ce90b53cbc..f4b7d2a5d4fbaeaa2fb8851ebbe76a43d179eceb 100644
--- a/app/code/Magento/Theme/Test/Unit/Model/ThemeValidatorTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Model/ThemeValidatorTest.php
@@ -81,9 +81,9 @@ class ThemeValidatorTest extends \PHPUnit_Framework_TestCase
         $result = $this->themeValidator->validateIsThemeInUse(['frontend/Magento/a']);
         $this->assertEquals(
             [
-                'frontend/Magento/a is in use in default config',
-                'frontend/Magento/a is in use in website websiteA',
-                'frontend/Magento/a is in use in store storeA'
+                '<error>frontend/Magento/a is in use in default config</error>',
+                '<error>frontend/Magento/a is in use in website websiteA</error>',
+                '<error>frontend/Magento/a is in use in store storeA</error>'
             ],
             $result
         );
diff --git a/app/code/Magento/Translation/Console/Command/UninstallLanguageCommand.php b/app/code/Magento/Translation/Console/Command/UninstallLanguageCommand.php
index b84237bb2cd32233a96cabb23f16ebf6ea0d06b4..a8c360f6444fa331a317fd9995f419b013597c45 100644
--- a/app/code/Magento/Translation/Console/Command/UninstallLanguageCommand.php
+++ b/app/code/Magento/Translation/Console/Command/UninstallLanguageCommand.php
@@ -19,6 +19,8 @@ use Magento\Framework\Setup\BackupRollbackFactory;
 
 /**
  * Command for uninstalling language and backup-code feature
+ * 
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
 class UninstallLanguageCommand extends Command
 {
@@ -151,7 +153,7 @@ class UninstallLanguageCommand extends Command
      */
     private function validate($package)
     {
-        $installedPackages = $this->composerInfo->getRootRequiredPackagesAndTypes();
+        $installedPackages = $this->composerInfo->getRootRequiredPackageTypesByName();
 
         if (isset($installedPackages[$package]) && $installedPackages[$package] === 'magento2-language') {
             return true;
diff --git a/app/code/Magento/Translation/Test/Unit/Console/Command/UninstallLanguageCommandTest.php b/app/code/Magento/Translation/Test/Unit/Console/Command/UninstallLanguageCommandTest.php
index 2f0cd02c6c9ea0f0e58128c6a999c6d86136fdf7..9ccb47dd1e92b4ac454e2228e5b78844f8e130d1 100644
--- a/app/code/Magento/Translation/Test/Unit/Console/Command/UninstallLanguageCommandTest.php
+++ b/app/code/Magento/Translation/Test/Unit/Console/Command/UninstallLanguageCommandTest.php
@@ -93,7 +93,7 @@ class UninstallLanguageCommandTest extends \PHPUnit_Framework_TestCase
             ->willReturn($dependencies);
 
         $this->composerInfo->expects($this->once())
-            ->method('getRootRequiredPackagesAndTypes')
+            ->method('getRootRequiredPackageTypesByName')
             ->willReturn(
                 [
                     'vendor/language-ua_ua' => 'magento2-language'
@@ -123,7 +123,7 @@ class UninstallLanguageCommandTest extends \PHPUnit_Framework_TestCase
             ->willReturn($dependencies);
 
         $this->composerInfo->expects($this->once())
-            ->method('getRootRequiredPackagesAndTypes')
+            ->method('getRootRequiredPackageTypesByName')
             ->willReturn(
                 [
                     'vendor/language-ua_ua' => 'magento2-language'
@@ -148,7 +148,7 @@ class UninstallLanguageCommandTest extends \PHPUnit_Framework_TestCase
             ->willReturn($dependencies);
 
         $this->composerInfo->expects($this->once())
-            ->method('getRootRequiredPackagesAndTypes')
+            ->method('getRootRequiredPackageTypesByName')
             ->willReturn(
                 [
                     'vendor/language-ua_ua' => 'magento2-language'
@@ -178,7 +178,7 @@ class UninstallLanguageCommandTest extends \PHPUnit_Framework_TestCase
             ->willReturn($dependencies);
 
         $this->composerInfo->expects($this->once())
-            ->method('getRootRequiredPackagesAndTypes')
+            ->method('getRootRequiredPackageTypesByName')
             ->willReturn(
                 [
                     'vendor/language-ua_ua' => 'library'
diff --git a/composer.json b/composer.json
index 2fca4d005a36670877caf6253c70e0bb38e92a90..de38e5f9054eaa949f908c24667d2eca249f0c4b 100644
--- a/composer.json
+++ b/composer.json
@@ -55,6 +55,7 @@
         "ext-iconv": "*",
         "ext-intl": "*",
         "ext-xsl": "*",
+        "ext-mbstring": "*",
         "sjparkinson/static-review": "~4.1",
         "fabpot/php-cs-fixer": "~1.2",
         "lusitanian/oauth": "~0.3"
diff --git a/composer.lock b/composer.lock
index 4e3421ad6e05957d87c2807e67fe0152cbf10bac..ad898f081b37863b7058659247c2f9facb8c4a70 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "32f26595c37e07bb66613d23424788e0",
+    "hash": "abd337bce9c7d09a56c1c40b3d2e4092",
     "packages": [
         {
             "name": "composer/composer",
@@ -49,7 +49,7 @@
                     "Composer": "src/"
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -261,7 +261,7 @@
                 "ZF1",
                 "framework"
             ],
-            "time": "2015-02-06 17:25:45"
+            "time": "2015-06-02 08:04:41"
         },
         {
             "name": "monolog/monolog",
@@ -567,7 +567,7 @@
                     "Symfony\\Component\\Finder\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -616,7 +616,7 @@
                     "Symfony\\Component\\Process\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -2693,7 +2693,7 @@
                     "src/"
                 ]
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "BSD-3-Clause"
             ],
@@ -3192,7 +3192,7 @@
                     "Symfony\\Component\\Config\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3252,7 +3252,7 @@
                     "Symfony\\Component\\DependencyInjection\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3310,7 +3310,7 @@
                     "Symfony\\Component\\EventDispatcher\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3359,7 +3359,7 @@
                     "Symfony\\Component\\Filesystem\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3408,7 +3408,7 @@
                     "Symfony\\Component\\Stopwatch\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3457,7 +3457,7 @@
                     "Symfony\\Component\\Yaml\\": ""
                 }
             },
-            "notification-url": "http://packagist.org/downloads/",
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -3499,6 +3499,7 @@
         "ext-curl": "*",
         "ext-iconv": "*",
         "ext-intl": "*",
-        "ext-xsl": "*"
+        "ext-xsl": "*",
+        "ext-mbstring": "*"
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/ComposerInformationTest.php b/dev/tests/integration/testsuite/Magento/Framework/Composer/ComposerInformationTest.php
similarity index 83%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/ComposerInformationTest.php
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/ComposerInformationTest.php
index cdcf2ca0817ffc06a9d5fc2793344ca3b535dacf..1fa911de8e967300eddd85a7c73390d011ce4f82 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Model/ComposerInformationTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/ComposerInformationTest.php
@@ -4,10 +4,10 @@
  * See COPYING.txt for license details.
  */
 
-namespace Magento\Setup\Model;
+namespace Magento\Framework\Composer;
 
 /**
- * Tests Magento\Setup\Model\ComposerInformation
+ * Tests Magento\Framework\ComposerInformation
  */
 class ComposerInformationTest extends \PHPUnit_Framework_TestCase
 {
@@ -84,6 +84,22 @@ class ComposerInformationTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+    /**
+     * @param $composerDir string Directory under _files that contains composer files
+     *
+     * @dataProvider getRequiredPhpVersionDataProvider
+     */
+    public function testGetRootRequiredPackagesAndTypes($composerDir)
+    {
+        $this->setupDirectoryMock($composerDir);
+        $composerInfo = new ComposerInformation($this->filesystemMock, $this->ioMock);
+
+        $requiredPackagesAndTypes = $composerInfo->getRootRequiredPackageTypesByName();
+
+        $this->assertArrayHasKey('composer/composer', $requiredPackagesAndTypes);
+        $this->assertEquals('library', $requiredPackagesAndTypes['composer/composer']);
+    }
+
     /**
      * Data provider that returns directories containing different types of composer files.
      *
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/composer.json b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/composer.json
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/composer.json
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/composer.json
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/composer.lock b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/composer.lock
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/composer.lock
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/composer.lock
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/vendor/README b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/vendor/README
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromClone/vendor/README
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromClone/vendor/README
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/composer.json b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/composer.json
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.json
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/composer.lock b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/composer.lock
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/vendor/README b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/vendor/README
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testFromCreateProject/vendor/README
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/vendor/README
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.json
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.json
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/vendor/README b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/vendor/README
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/vendor/README
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/vendor/README
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/vendor_path.php b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/vendor_path.php
similarity index 100%
rename from dev/tests/integration/testsuite/Magento/Setup/Model/_files/vendor_path.php
rename to dev/tests/integration/testsuite/Magento/Framework/Composer/_files/vendor_path.php
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
index f378bb929e0aaddb26a649b91afdf5b056b1b857..619996d9efcf8cc6bdced2abda23eb728c8071ad 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php
@@ -276,6 +276,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase
             /** @var \Magento\Framework\Search\Document $document */
             $actualIds[] = $document->getId();
         }
+        sort($actualIds);
         $this->assertEquals($expectedIds, $actualIds);
     }
 
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
index 4cfed53e55352a8a77865f52862073abbf657605..c563b677620382c5b08c868fec60488247f6d359 100755
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
@@ -3658,4 +3658,5 @@ return [
     ['Magento\Centinel\CreateOrderTest'],
     ['Magento\Payment\Model\Checks\PaymentMethodChecksInterface', 'Magento\Payment\Model\MethodInterface'],
     ['Magento\GiftMessage\Model\Plugin\TotalsDataProcessorPlugin'],
+    ['Magento\Catalog\Model\Product\Attribute\Backend\Startdate', 'Magento\Catalog\Model\Attribute\Backend\Startdate'],
 ];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index cd660a65eb1223dad2b303f80f1b0eac7e0280d8..b2ac847c21585fcfb2f533d683401d3d2df00319 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -2245,7 +2245,7 @@ return [
     ['getIdentities', 'Magento\Sales\Block\Reorder\Sidebar'],
     ['assignData', 'Magento\OfflinePayments\Model\Checkmo'],
     ['timeShift', 'Magento\Reports\Model\Resource\Report\Collection'],
-    ['Magento\Catalog\Model\Product\Attribute\Backend\Startdate', 'Magento\Catalog\Model\Attribute\Backend\Startdate'],
+    ['getFilePath', 'Magento\MediaStorage\Model\File\Storage\Request'],
     ['_getStoreTimezoneUtcOffset', 'Magento\Reports\Model\Resource\Report\AbstractReport'],
     ['_dateToUtc', 'Magento\Reports\Model\Resource\Report\AbstractReport'],
     ['getDataSetDefault', 'Magento\Framework\Object'],
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
index cfb1078156bf214d798499c6e2bc9962702d8608..10bc4fee0abb74c55108c2f72e044c64ef9d5f9b 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php
@@ -166,6 +166,7 @@ return [
     ['_filesystem', 'Magento\Core\Model\Resource\Setup\Migration', '_directory'],
     ['_filesystem', 'Magento\Core\Model\Theme\Collection', '_directory'],
     ['_mediaBaseDirectory', 'Magento\MediaStorage\Model\Resource\File\Storage\File'],
+    ['_mediaBaseDirectory', 'Magento\MediaStorage\Model\File\Storage\Database\AbstractDatabase'],
     ['_dbHelper', 'Magento\MediaStorage\Model\Resource\File\Storage\File'],
     ['_filesystem', 'Magento\Core\Model\Theme\CopyService', '_directory'],
     ['_baseDir', 'Magento\Core\Model\Theme\Collection'],
diff --git a/lib/internal/Magento/Framework/Composer/ComposerInformation.php b/lib/internal/Magento/Framework/Composer/ComposerInformation.php
index 5ba195f386dba1d3e489993b423c00bde17aa295..852ef6aebef3fcfea1214a46b696715a1d58b52d 100644
--- a/lib/internal/Magento/Framework/Composer/ComposerInformation.php
+++ b/lib/internal/Magento/Framework/Composer/ComposerInformation.php
@@ -7,6 +7,8 @@
 namespace Magento\Framework\Composer;
 
 use Composer\Factory as ComposerFactory;
+use Composer\IO\BufferIO;
+use Composer\Package\Link;
 use Composer\Package\PackageInterface;
 use Magento\Framework\App\Filesystem\DirectoryList;
 use Magento\Framework\Filesystem;
@@ -30,15 +32,28 @@ class ComposerInformation
      * Constructor
      *
      * @param Filesystem $filesystem
+     * @param BufferIO $io
+     * @throws \Exception
      */
     public function __construct(
-        Filesystem $filesystem
+        Filesystem $filesystem,
+        BufferIO $io
     ) {
-        $vendor = $filesystem->getDirectoryRead(DirectoryList::CONFIG)->getAbsolutePath('vendor_path.php');
-        $vendorPath = $filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath() . include $vendor;
+        // composer.json is in same directory as vendor
+        $vendorPath = $filesystem->getDirectoryRead(DirectoryList::CONFIG)->getAbsolutePath('vendor_path.php');
+        $vendorDir = require "{$vendorPath}";
+        $composerJson = $filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath()
+            . "/{$vendorDir}/../composer.json";
+
+        $composerJsonRealPath = realpath($composerJson);
+        if ($composerJsonRealPath === false) {
+            throw new \Exception('Composer file not found: ' . $composerJson);
+        }
+
+        putenv('COMPOSER_HOME=' . $filesystem->getDirectoryRead(DirectoryList::COMPOSER_HOME)->getAbsolutePath());
+
         // Create Composer
-        $io = new \Composer\IO\BufferIO();
-        $this->composer = ComposerFactory::create($io, $vendorPath . '/../composer.json');
+        $this->composer = ComposerFactory::create($io, $composerJson);
         $this->locker = $this->composer->getLocker();
     }
 
@@ -55,12 +70,16 @@ class ComposerInformation
             $requiredPhpVersion =  $allPlatformReqs['php']->getPrettyConstraint();
         } else {
             $packages = $this->locker->getLockedRepository()->getPackages();
+            /** @var PackageInterface $package */
             foreach ($packages as $package) {
-                /** @var \Composer\Package\CompletePackage $package */
-                $packageName = $package->getPrettyName();
-                if ($packageName === 'magento/product-community-edition') {
-                    $phpRequirementLink = $package->getRequires()['php'];
-                    $requiredPhpVersion = $phpRequirementLink->getPrettyConstraint();
+                if ($package instanceof PackageInterface) {
+                    $packageName = $package->getPrettyName();
+                    if ($packageName === 'magento/product-community-edition') {
+                        $phpRequirementLink = $package->getRequires()['php'];
+                        if ($phpRequirementLink instanceof Link) {
+                            $requiredPhpVersion = $phpRequirementLink->getPrettyConstraint();
+                        }
+                    }
                 }
             }
         }
@@ -81,32 +100,23 @@ class ComposerInformation
      */
     public function getRequiredExtensions()
     {
-        if ($this->isMagentoRoot()) {
-            $allPlatformReqs = $this->locker->getPlatformRequirements(true);
-            foreach ($allPlatformReqs as $reqIndex => $constraint) {
-                if (substr($reqIndex, 0, 4) === 'ext-') {
-                    $requiredExtensions[] = substr($reqIndex, 4);
-                }
-            }
-        } else {
-            $requiredExtensions = [];
+        $requiredExtensions = [];
+        $allPlatformReqs = array_keys($this->locker->getPlatformRequirements(true));
 
+        if (!$this->isMagentoRoot()) {
             /** @var \Composer\Package\CompletePackage $package */
             foreach ($this->locker->getLockedRepository()->getPackages() as $package) {
-                $requires = $package->getRequires();
-                $requires = array_merge($requires, $package->getDevRequires());
-                foreach ($requires as $reqIndex => $constraint) {
-                    if (substr($reqIndex, 0, 4) === 'ext-') {
-                        $requiredExtensions[] = substr($reqIndex, 4);
-                    }
-                }
+                $requires = array_keys($package->getRequires());
+                $requires = array_merge($requires, array_keys($package->getDevRequires()));
+                $allPlatformReqs = array_merge($allPlatformReqs, $requires);
             }
         }
-
-        if (!isset($requiredExtensions)) {
-            throw new \Exception('Cannot find extensions in \'composer.lock\' file');
+        foreach ($allPlatformReqs as $reqIndex) {
+            if (substr($reqIndex, 0, 4) === 'ext-') {
+                $requiredExtensions[] = substr($reqIndex, 4);
+            }
         }
-        return $requiredExtensions;
+        return array_unique($requiredExtensions);
     }
 
     /**
@@ -129,7 +139,7 @@ class ComposerInformation
      *
      * @return array
      */
-    public function getRootRequiredPackagesAndTypes()
+    public function getRootRequiredPackageTypesByName()
     {
         $packages = [];
         /** @var PackageInterface $package */
@@ -147,6 +157,7 @@ class ComposerInformation
     private function isMagentoRoot()
     {
         $rootPackage = $this->composer->getPackage();
-        return ('magento/magento2ce' == $rootPackage->getName());
+
+        return preg_match('/magento\/magento2.e/', $rootPackage->getName());
     }
 }
diff --git a/pub/get.php b/pub/get.php
index 68626e0a57e0a5ba25cfff4e41c461d87c367c9a..9888d7627acaea160f3d4a18297941fba2cb60dc 100755
--- a/pub/get.php
+++ b/pub/get.php
@@ -8,13 +8,14 @@
 
 use Magento\Framework\App\Cache\Frontend\Factory;
 use Magento\Framework\App\ObjectManagerFactory;
+use Magento\Framework\HTTP\PhpEnvironment\Request;
+use Magento\Framework\Stdlib\Cookie\PhpCookieReader;
 
 require dirname(__DIR__) . '/app/bootstrap.php';
 
 $mediaDirectory = null;
 $allowedResources = [];
-$configCacheFile = dirname(__DIR__) . '/var/resource_config.json';
-$relativeFilename = null;
+$configCacheFile = BP . '/var/resource_config.json';
 
 $isAllowed = function ($resource, array $allowedResources) {
     $isResourceAllowed = false;
@@ -26,39 +27,39 @@ $isAllowed = function ($resource, array $allowedResources) {
     return $isResourceAllowed;
 };
 
+$request = new \Magento\MediaStorage\Model\File\Storage\Request(new Request(new PhpCookieReader()));
+$relativePath = $request->getPathInfo();
 if (file_exists($configCacheFile) && is_readable($configCacheFile)) {
     $config = json_decode(file_get_contents($configCacheFile), true);
 
     //checking update time
     if (filemtime($configCacheFile) + $config['update_time'] > time()) {
-        $mediaDirectory = trim(str_replace(__DIR__, '', $config['media_directory']), '/');
-        $allowedResources = array_merge($allowedResources, $config['allowed_resources']);
-    }
-}
-
-// Serve file if it's materialized
-$request = new \Magento\MediaStorage\Model\File\Storage\Request(__DIR__);
-if ($mediaDirectory) {
-    if (0 !== stripos($request->getPathInfo(), $mediaDirectory . '/') || is_dir($request->getFilePath())) {
-        header('HTTP/1.0 404 Not Found');
-        exit;
-    }
+        $mediaDirectory = $config['media_directory'];
+        $allowedResources = $config['allowed_resources'];
 
-    $relativeFilename = str_replace($mediaDirectory . '/', '', $request->getPathInfo());
-    if (!$isAllowed($relativeFilename, $allowedResources)) {
-        header('HTTP/1.0 404 Not Found');
-        exit;
-    }
-
-    if (is_readable($request->getFilePath())) {
-        $transfer = new \Magento\Framework\File\Transfer\Adapter\Http(
-            new \Magento\Framework\HTTP\PhpEnvironment\Response(),
-            new \Magento\Framework\File\Mime()
-        );
-        $transfer->send($request->getFilePath());
-        exit;
+        // Serve file if it's materialized
+        if ($mediaDirectory) {
+            if (!$isAllowed($relativePath, $allowedResources)) {
+                header('HTTP/1.0 404 Not Found');
+                exit;
+            }
+            $mediaAbsPath = $mediaDirectory . '/' . $relativePath;
+            if (is_readable($mediaAbsPath)) {
+                if (is_dir($mediaAbsPath)) {
+                    header('HTTP/1.0 404 Not Found');
+                    exit;
+                }
+                $transfer = new \Magento\Framework\File\Transfer\Adapter\Http(
+                    new \Magento\Framework\HTTP\PhpEnvironment\Response(),
+                    new \Magento\Framework\File\Mime()
+                );
+                $transfer->send($mediaAbsPath);
+                exit;
+            }
+        }
     }
 }
+
 // Materialize file in application
 $params = $_SERVER;
 if (empty($mediaDirectory)) {
@@ -70,12 +71,10 @@ $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
 $app = $bootstrap->createApplication(
     'Magento\MediaStorage\App\Media',
     [
-        'request' => $request,
-        'workingDirectory' => __DIR__,
         'mediaDirectory' => $mediaDirectory,
         'configCacheFile' => $configCacheFile,
         'isAllowed' => $isAllowed,
-        'relativeFileName' => $relativeFilename,
+        'relativeFileName' => $relativePath,
     ]
 );
 $bootstrap->run($app);
diff --git a/setup/src/Magento/Setup/Controller/Environment.php b/setup/src/Magento/Setup/Controller/Environment.php
index e88ed5e59602a0485f5bbfc2bf42bbdc69404b8f..1be039847995bec34c7366efc63413b0876de890 100644
--- a/setup/src/Magento/Setup/Controller/Environment.php
+++ b/setup/src/Magento/Setup/Controller/Environment.php
@@ -8,7 +8,7 @@ namespace Magento\Setup\Controller;
 use Composer\Package\Version\VersionParser;
 use Zend\Mvc\Controller\AbstractActionController;
 use Zend\View\Model\JsonModel;
-use Magento\Setup\Model\ComposerInformation;
+use Magento\Framework\Composer\ComposerInformation;
 use Magento\Setup\Model\PhpInformation;
 use Magento\Setup\Model\FilePermissions;
 
diff --git a/setup/src/Magento/Setup/Model/ComposerInformation.php b/setup/src/Magento/Setup/Model/ComposerInformation.php
deleted file mode 100644
index 431f4c8243f7b800ac9c07729c0d52d017e11de5..0000000000000000000000000000000000000000
--- a/setup/src/Magento/Setup/Model/ComposerInformation.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-namespace Magento\Setup\Model;
-
-use Composer\Factory as ComposerFactory;
-use Composer\IO\BufferIO;
-use Composer\Package\Link;
-use Composer\Package\PackageInterface;
-use Magento\Framework\App\Filesystem\DirectoryList;
-use Magento\Framework\Filesystem;
-
-/**
- * Class ComposerInformation uses Composer to determine dependency information.
- */
-class ComposerInformation
-{
-    /**
-     * @var \Composer\Composer
-     */
-    private $composer;
-
-    /**
-     * @var \Composer\Package\Locker
-     */
-    private $locker;
-
-    /**
-     * Constructor
-     *
-     * @param Filesystem $filesystem
-     * @param BufferIO $io
-     * @throws \Exception
-     */
-    public function __construct(
-        Filesystem $filesystem,
-        BufferIO $io
-    ) {
-        // composer.json is in same directory as vendor
-        $vendorPath = $filesystem->getDirectoryRead(DirectoryList::CONFIG)->getAbsolutePath('vendor_path.php');
-        $vendorDir = require "{$vendorPath}";
-        $composerJson = $filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath()
-            . "/{$vendorDir}/../composer.json";
-
-        $composerJsonRealPath = realpath($composerJson);
-        if ($composerJsonRealPath === false) {
-            throw new \Exception('Composer file not found: ' . $composerJson);
-        }
-
-        putenv('COMPOSER_HOME=' . $filesystem->getDirectoryRead(DirectoryList::COMPOSER_HOME)->getAbsolutePath());
-
-        // Create Composer
-        $this->composer = ComposerFactory::create($io, $composerJson);
-        $this->locker = $this->composer->getLocker();
-    }
-
-    /**
-     * Retrieves required php version
-     *
-     * @return string
-     * @throws \Exception If attributes are missing in composer.lock file.
-     */
-    public function getRequiredPhpVersion()
-    {
-        if ($this->isMagentoRoot()) {
-            $allPlatformReqs = $this->locker->getPlatformRequirements(true);
-            $requiredPhpVersion =  $allPlatformReqs['php']->getPrettyConstraint();
-        } else {
-            $packages = $this->locker->getLockedRepository()->getPackages();
-            /** @var PackageInterface $package */
-            foreach ($packages as $package) {
-                if ($package instanceof PackageInterface) {
-                    $packageName = $package->getPrettyName();
-                    if ($packageName === 'magento/product-community-edition') {
-                        $phpRequirementLink = $package->getRequires()['php'];
-                        if ($phpRequirementLink instanceof Link) {
-                            $requiredPhpVersion = $phpRequirementLink->getPrettyConstraint();
-                        }
-                    }
-                }
-            }
-        }
-
-        if (!isset($requiredPhpVersion)) {
-            throw new \Exception('Cannot find php version requirement in \'composer.lock\' file');
-        }
-        return $requiredPhpVersion;
-    }
-
-    /**
-     * Retrieve list of required extensions
-     *
-     * Collect required extensions from composer.lock file
-     *
-     * @return array
-     * @throws \Exception If attributes are missing in composer.lock file.
-     */
-    public function getRequiredExtensions()
-    {
-        $requiredExtensions = [];
-        $allPlatformReqs = array_keys($this->locker->getPlatformRequirements(true));
-
-        if (!$this->isMagentoRoot()) {
-            /** @var \Composer\Package\CompletePackage $package */
-            foreach ($this->locker->getLockedRepository()->getPackages() as $package) {
-                $requires = array_keys($package->getRequires());
-                $requires = array_merge($requires, array_keys($package->getDevRequires()));
-                $allPlatformReqs = array_merge($allPlatformReqs, $requires);
-            }
-        }
-        foreach ($allPlatformReqs as $reqIndex) {
-            if (substr($reqIndex, 0, 4) === 'ext-') {
-                $requiredExtensions[] = substr($reqIndex, 4);
-            }
-        }
-        return array_unique($requiredExtensions);
-    }
-
-    /**
-     * Determines if Magento is the root package or it is included as a requirement.
-     *
-     * @return bool
-     */
-    private function isMagentoRoot()
-    {
-        $rootPackage = $this->composer->getPackage();
-
-        return preg_match('/magento\/magento2.e/', $rootPackage->getName());
-    }
-}