change architecture from inheritance to composition

This commit is contained in:
Jörn Friedrich Dreyer 2014-06-17 22:06:56 +02:00
parent 9335a5f07f
commit 5cae863408
7 changed files with 131 additions and 65 deletions

View file

@ -325,32 +325,36 @@ class Filesystem {
$userObject = \OC_User::getManager()->get($user);
if (!is_null($userObject)) {
$homeStorage = \OC_Config::getValue( 'objectstore', array(
//default home storage configuration:
'class' => '\OC\Files\Storage\Home',
'arguments' => array()
));
// sanity checks
if (empty($homeStorage['class'])) {
\OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
}
if (!isset($homeStorage['arguments'])) {
$homeStorage['arguments'] = array();
$homeStorage = \OC_Config::getValue( 'objectstore' );
if (!empty($homeStorage)) {
// sanity checks
if (empty($homeStorage['class'])) {
\OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
}
if (!isset($homeStorage['arguments'])) {
$homeStorage['arguments'] = array();
}
// instantiate object store implementation
$homeStorage['arguments']['objectstore'] = new $homeStorage['class']($homeStorage['arguments']);
// mount with home object store implementation
$homeStorage['class'] = '\OC\Files\ObjectStore\HomeObjectStoreStorage';
} else {
$homeStorage = array(
//default home storage configuration:
'class' => '\OC\Files\Storage\Home',
'arguments' => array()
);
}
$homeStorage['arguments']['user'] = $userObject;
// check for legacy home id (<= 5.0.12)
if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) {
$homeStorage['arguments']['legacy'] = true;
}
self::mount($homeStorage['class'], $homeStorage['arguments'], $user);
$home = \OC\Files\Filesystem::getStorage($user);
if ( $home->instanceOfStorage('\OC\Files\ObjectStore\AbstractObjectStore') ) {
//create the files folder in the cache when mounting the objectstore for a user
if ( ! $home->is_dir('files') ) {
$home->mkdir('files');
}
}
}
else {
self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);

View file

@ -0,0 +1,34 @@
<?php
/**
* @author Jörn Friedrich Dreyer
* @copyright (c) 2014 Jörn Friedrich Dreyer <jfd@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Files\ObjectStore;
class HomeObjectStoreStorage extends ObjectStoreStorage {
public function __construct($params) {
parent::__construct($params);
//initialize cache with root directory in cache
if ( ! $this->is_dir('files') ) {
$this->mkdir('files');
}
}
}

View file

@ -20,32 +20,14 @@
namespace OC\Files\ObjectStore;
abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
use OCP\Files\ObjectStore\IObjectStore;
class ObjectStoreStorage extends \OC\Files\Storage\Common {
/**
* @param string $urn the unified resource name used to identify the object
* @param string $tmpFile path to the local temporary file that the object
* should be loaded from
* @return void
* @throws Exception when something goes wrong, message will be logged
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore
*/
abstract protected function createObject($urn, $tmpFile = null);
/**
* @param string $urn the unified resource name used to identify the object
* @param string $tmpFile path to the local temporary file that should be
* used to store the object
* @return void
* @throws Exception when something goes wrong, message will be logged
*/
abstract protected function getObject($urn, $tmpFile);
/**
* @param string $urn the unified resource name used to identify the object
* @return void
* @throws Exception when something goes wrong, message will be logged
*/
abstract protected function deleteObject($urn);
protected $objectStore;
/**
* @var \OC\User\User $user
@ -58,11 +40,16 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
private static $tmpFiles = array();
public function __construct($params) {
if (isset($params['user']) && is_object($params['user'])) {
if (isset($params['user']) && $params['user'] instanceof \OC\User\User) {
$this->user = $params['user'];
} else {
$this->user = null;
}
if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
$this->objectStore = $params['objectstore'];
} else {
throw new \Exception('missing IObjectStore instance');
}
//initialize cache with root directory in cache
if ( ! $this->is_dir('/') ) {
$this->mkdir('/');
@ -243,7 +230,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
return $this->rmdir($path);
}
try {
$this->deleteObject($this->getURN($stat['fileid']));
$this->objectStore->deleteObject($this->getURN($stat['fileid']));
} catch (\Exception $ex) {
if ($ex->getCode() !== 404) {
\OCP\Util::writeLog('objectstore', 'Could not delete object: '.$ex->getMessage(), \OCP\Util::ERROR);
@ -269,7 +256,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
$tmpFile = \OC_Helper::tmpFile();
self::$tmpFiles[$tmpFile] = $path;
try {
$this->getObject($this->getURN($stat['fileid']), $tmpFile);
$this->objectStore->getObject($this->getURN($stat['fileid']), $tmpFile);
} catch (\Exception $ex) {
\OCP\Util::writeLog('objectstore', 'Could not get object: '.$ex->getMessage(), \OCP\Util::ERROR);
return false;
@ -376,7 +363,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
);
$fileId = $this->getCache()->put($path, $stat);
try {
$this->createObject($this->getURN($fileId));
$this->objectStore->updateObject($this->getURN($fileId));
} catch (\Exception $ex) {
$this->getCache()->remove($path);
\OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR);
@ -424,7 +411,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common {
$fileId = $this->getCache()->put($path, $stat);
try {
//upload to object storage
$this->createObject($this->getURN($fileId), $tmpFile);
$this->objectStore->updateObject($this->getURN($fileId), $tmpFile);
} catch (\Exception $ex) {
$this->getCache()->remove($path);
\OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR);

View file

@ -23,7 +23,7 @@ namespace OC\Files\ObjectStore;
use Guzzle\Http\Exception\ClientErrorResponseException;
use OpenCloud\OpenStack;
class Swift extends AbstractObjectStore {
class Swift implements \OCP\Files\ObjectStore\IObjectStore {
/**
* @var \OpenCloud\ObjectStore\Service
@ -78,19 +78,22 @@ class Swift extends AbstractObjectStore {
throw $ex;
}
}
//set the user via parent constructor, also initializes the root of the filecache
parent::__construct($params);
}
/**
* @param string $urn Unified Resource Name
* @param string $tmpFile
* @return void
* @throws Exception from openstack lib when something goes wrong
*/
protected function deleteObject($urn) {
$object = $this->container->getObject($urn);
$object->delete();
public function updateObject($urn, $tmpFile = null) {
$fileData = '';
if ($tmpFile) {
$fileData = fopen($tmpFile, 'r');
}
$this->container->uploadObject($urn, $fileData);
}
/**
@ -99,7 +102,7 @@ class Swift extends AbstractObjectStore {
* @return void
* @throws Exception from openstack lib when something goes wrong
*/
protected function getObject($urn, $tmpFile) {
public function getObject($urn, $tmpFile) {
$object = $this->container->getObject($urn);
/** @var $objectContent \Guzzle\Http\EntityBody **/
@ -112,17 +115,12 @@ class Swift extends AbstractObjectStore {
/**
* @param string $urn Unified Resource Name
* @param string $tmpFile
* @return void
* @throws Exception from openstack lib when something goes wrong
*/
protected function createObject($urn, $tmpFile = null) {
$fileData = '';
if ($tmpFile) {
$fileData = fopen($tmpFile, 'r');
}
$this->container->uploadObject($urn, $fileData);
public function deleteObject($urn) {
$object = $this->container->getObject($urn);
$object->delete();
}
public function deleteContainer($recursive = false) {

View file

@ -32,11 +32,17 @@ class OC_Util {
private static function initObjectStoreRootFS($config) {
// check misconfiguration
if (empty($config['class'])) {
//FIXME log error?
\OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
}
if (!isset($config['arguments'])) {
$config['arguments'] = array();
}
// instantiate object store implementation
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
// mount with plain / root object store implementation
$config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
// mount object storage as root
\OC\Files\Filesystem::initMounts();
if(!self::$rootMounted) {
@ -94,7 +100,7 @@ class OC_Util {
* @var \OC\Files\Storage\Storage $storage
*/
if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
|| $storage->instanceOfStorage('\OC\Files\ObjectStore\AbstractObjectStore')
|| $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
) {
if (is_object($storage->getUser())) {
$user = $storage->getUser()->getUID();

View file

@ -0,0 +1,32 @@
<?php
namespace OCP\Files\ObjectStore;
interface IObjectStore {
/**
* @param string $urn the unified resource name used to identify the object
* @param string $tmpFile path to the local temporary file that should be
* used to store the object
* @return void
* @throws Exception when something goes wrong, message will be logged
*/
function getObject($urn, $tmpFile);
/**
* @param string $urn the unified resource name used to identify the object
* @param string $tmpFile path to the local temporary file that the object
* should be loaded from
* @return void
* @throws Exception when something goes wrong, message will be logged
*/
function updateObject($urn, $tmpFile = null);
/**
* @param string $urn the unified resource name used to identify the object
* @return void
* @throws Exception when something goes wrong, message will be logged
*/
function deleteObject($urn);
}

View file

@ -20,6 +20,7 @@
namespace OCA\ObjectStore\Tests\Unit;
use OC\Files\ObjectStore\ObjectStoreStorage;
use OC\Files\ObjectStore\Swift as ObjectStoreToTest;
use PHPUnit_Framework_TestCase;
@ -30,6 +31,8 @@ class Swift extends PHPUnit_Framework_TestCase {
* @var \OC\Files\ObjectStore\Swift $storage
*/
private $storage;
private $objectStorage;
public function setUp() {
@ -67,14 +70,16 @@ class Swift extends PHPUnit_Framework_TestCase {
'serviceName' => 'swift', //trystack uses swift by default, the lib defaults to 'cloudFiles' if omitted
'user' => \OC_User::getManager()->get($userName)
);
$this->storage = new ObjectStoreToTest($params);
$this->objectStorage = new ObjectStoreToTest($params);
$params['objectstore'] = $this->objectStorage;
$this->storage = new ObjectStoreStorage($params);
}
public function tearDown() {
if (is_null($this->storage)) {
return;
}
$this->storage->deleteContainer(true);
$this->objectStorage->deleteContainer(true);
$this->storage->getCache()->clear();
//TODO how do I clear hooks?
}