Path: blob/trunk/third_party/closure/goog/fs/entryimpl.js
2868 views
// Copyright 2013 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Concrete implementations of the16* goog.fs.DirectoryEntry, and goog.fs.FileEntry interfaces.17*/18goog.provide('goog.fs.DirectoryEntryImpl');19goog.provide('goog.fs.EntryImpl');20goog.provide('goog.fs.FileEntryImpl');2122goog.require('goog.array');23goog.require('goog.async.Deferred');24goog.require('goog.fs.DirectoryEntry');25goog.require('goog.fs.Entry');26goog.require('goog.fs.Error');27goog.require('goog.fs.FileEntry');28goog.require('goog.fs.FileWriter');29goog.require('goog.functions');30goog.require('goog.string');31323334/**35* Base class for concrete implementations of goog.fs.Entry.36* @param {!goog.fs.FileSystem} fs The wrapped filesystem.37* @param {!Entry} entry The underlying Entry object.38* @constructor39* @implements {goog.fs.Entry}40*/41goog.fs.EntryImpl = function(fs, entry) {42/**43* The wrapped filesystem.44*45* @type {!goog.fs.FileSystem}46* @private47*/48this.fs_ = fs;4950/**51* The underlying Entry object.52*53* @type {!Entry}54* @private55*/56this.entry_ = entry;57};585960/** @override */61goog.fs.EntryImpl.prototype.isFile = function() {62return this.entry_.isFile;63};646566/** @override */67goog.fs.EntryImpl.prototype.isDirectory = function() {68return this.entry_.isDirectory;69};707172/** @override */73goog.fs.EntryImpl.prototype.getName = function() {74return this.entry_.name;75};767778/** @override */79goog.fs.EntryImpl.prototype.getFullPath = function() {80return this.entry_.fullPath;81};828384/** @override */85goog.fs.EntryImpl.prototype.getFileSystem = function() {86return this.fs_;87};888990/** @override */91goog.fs.EntryImpl.prototype.getLastModified = function() {92return this.getMetadata().addCallback(function(metadata) {93return metadata.modificationTime;94});95};969798/** @override */99goog.fs.EntryImpl.prototype.getMetadata = function() {100var d = new goog.async.Deferred();101102this.entry_.getMetadata(function(metadata) {103d.callback(metadata);104}, goog.bind(function(err) {105var msg = 'retrieving metadata for ' + this.getFullPath();106d.errback(new goog.fs.Error(err, msg));107}, this));108return d;109};110111112/** @override */113goog.fs.EntryImpl.prototype.moveTo = function(parent, opt_newName) {114var d = new goog.async.Deferred();115this.entry_.moveTo(116/** @type {!goog.fs.DirectoryEntryImpl} */ (parent).dir_, opt_newName,117goog.bind(function(entry) {118d.callback(this.wrapEntry(entry));119}, this), goog.bind(function(err) {120var msg = 'moving ' + this.getFullPath() + ' into ' +121parent.getFullPath() +122(opt_newName ? ', renaming to ' + opt_newName : '');123d.errback(new goog.fs.Error(err, msg));124}, this));125return d;126};127128129/** @override */130goog.fs.EntryImpl.prototype.copyTo = function(parent, opt_newName) {131var d = new goog.async.Deferred();132this.entry_.copyTo(133/** @type {!goog.fs.DirectoryEntryImpl} */ (parent).dir_, opt_newName,134goog.bind(function(entry) {135d.callback(this.wrapEntry(entry));136}, this), goog.bind(function(err) {137var msg = 'copying ' + this.getFullPath() + ' into ' +138parent.getFullPath() +139(opt_newName ? ', renaming to ' + opt_newName : '');140d.errback(new goog.fs.Error(err, msg));141}, this));142return d;143};144145146/** @override */147goog.fs.EntryImpl.prototype.wrapEntry = function(entry) {148return entry.isFile ?149new goog.fs.FileEntryImpl(this.fs_, /** @type {!FileEntry} */ (entry)) :150new goog.fs.DirectoryEntryImpl(151this.fs_, /** @type {!DirectoryEntry} */ (entry));152};153154155/** @override */156goog.fs.EntryImpl.prototype.toUrl = function(opt_mimeType) {157return this.entry_.toURL(opt_mimeType);158};159160161/** @override */162goog.fs.EntryImpl.prototype.toUri = goog.fs.EntryImpl.prototype.toUrl;163164165/** @override */166goog.fs.EntryImpl.prototype.remove = function() {167var d = new goog.async.Deferred();168this.entry_.remove(169goog.bind(d.callback, d, true /* result */), goog.bind(function(err) {170var msg = 'removing ' + this.getFullPath();171d.errback(new goog.fs.Error(err, msg));172}, this));173return d;174};175176177/** @override */178goog.fs.EntryImpl.prototype.getParent = function() {179var d = new goog.async.Deferred();180this.entry_.getParent(goog.bind(function(parent) {181d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, parent));182}, this), goog.bind(function(err) {183var msg = 'getting parent of ' + this.getFullPath();184d.errback(new goog.fs.Error(err, msg));185}, this));186return d;187};188189190191/**192* A directory in a local FileSystem.193*194* This should not be instantiated directly. Instead, it should be accessed via195* {@link goog.fs.FileSystem#getRoot} or196* {@link goog.fs.DirectoryEntry#getDirectoryEntry}.197*198* @param {!goog.fs.FileSystem} fs The wrapped filesystem.199* @param {!DirectoryEntry} dir The underlying DirectoryEntry object.200* @constructor201* @extends {goog.fs.EntryImpl}202* @implements {goog.fs.DirectoryEntry}203* @final204*/205goog.fs.DirectoryEntryImpl = function(fs, dir) {206goog.fs.DirectoryEntryImpl.base(this, 'constructor', fs, dir);207208/**209* The underlying DirectoryEntry object.210*211* @type {!DirectoryEntry}212* @private213*/214this.dir_ = dir;215};216goog.inherits(goog.fs.DirectoryEntryImpl, goog.fs.EntryImpl);217218219/** @override */220goog.fs.DirectoryEntryImpl.prototype.getFile = function(path, opt_behavior) {221var d = new goog.async.Deferred();222this.dir_.getFile(223path, this.getOptions_(opt_behavior), goog.bind(function(entry) {224d.callback(new goog.fs.FileEntryImpl(this.fs_, entry));225}, this), goog.bind(function(err) {226var msg = 'loading file ' + path + ' from ' + this.getFullPath();227d.errback(new goog.fs.Error(err, msg));228}, this));229return d;230};231232233/** @override */234goog.fs.DirectoryEntryImpl.prototype.getDirectory = function(235path, opt_behavior) {236var d = new goog.async.Deferred();237this.dir_.getDirectory(238path, this.getOptions_(opt_behavior), goog.bind(function(entry) {239d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, entry));240}, this), goog.bind(function(err) {241var msg = 'loading directory ' + path + ' from ' + this.getFullPath();242d.errback(new goog.fs.Error(err, msg));243}, this));244return d;245};246247248/** @override */249goog.fs.DirectoryEntryImpl.prototype.createPath = function(path) {250// If the path begins at the root, reinvoke createPath on the root directory.251if (goog.string.startsWith(path, '/')) {252var root = this.getFileSystem().getRoot();253if (this.getFullPath() != root.getFullPath()) {254return root.createPath(path);255}256}257258// Filter out any empty path components caused by '//' or a leading slash.259var parts = goog.array.filter(path.split('/'), goog.functions.identity);260261/**262* @param {goog.fs.DirectoryEntryImpl} dir263* @return {!goog.async.Deferred}264*/265function getNextDirectory(dir) {266if (!parts.length) {267return goog.async.Deferred.succeed(dir);268}269270var def;271var nextDir = parts.shift();272273if (nextDir == '..') {274def = dir.getParent();275} else if (nextDir == '.') {276def = goog.async.Deferred.succeed(dir);277} else {278def = dir.getDirectory(nextDir, goog.fs.DirectoryEntry.Behavior.CREATE);279}280return def.addCallback(getNextDirectory);281}282283return getNextDirectory(this);284};285286287/** @override */288goog.fs.DirectoryEntryImpl.prototype.listDirectory = function() {289var d = new goog.async.Deferred();290var reader = this.dir_.createReader();291var results = [];292293var errorCallback = goog.bind(function(err) {294var msg = 'listing directory ' + this.getFullPath();295d.errback(new goog.fs.Error(err, msg));296}, this);297298var successCallback = goog.bind(function(entries) {299if (entries.length) {300for (var i = 0, entry; entry = entries[i]; i++) {301results.push(this.wrapEntry(entry));302}303reader.readEntries(successCallback, errorCallback);304} else {305d.callback(results);306}307}, this);308309reader.readEntries(successCallback, errorCallback);310return d;311};312313314/** @override */315goog.fs.DirectoryEntryImpl.prototype.removeRecursively = function() {316var d = new goog.async.Deferred();317this.dir_.removeRecursively(318goog.bind(d.callback, d, true /* result */), goog.bind(function(err) {319var msg = 'removing ' + this.getFullPath() + ' recursively';320d.errback(new goog.fs.Error(err, msg));321}, this));322return d;323};324325326/**327* Converts a value in the Behavior enum into an options object expected by the328* File API.329*330* @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for331* existing files.332* @return {!Object<boolean>} The options object expected by the File API.333* @private334*/335goog.fs.DirectoryEntryImpl.prototype.getOptions_ = function(opt_behavior) {336if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {337return {'create': true};338} else if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {339return {'create': true, 'exclusive': true};340} else {341return {};342}343};344345346347/**348* A file in a local filesystem.349*350* This should not be instantiated directly. Instead, it should be accessed via351* {@link goog.fs.DirectoryEntry#getFile}.352*353* @param {!goog.fs.FileSystem} fs The wrapped filesystem.354* @param {!FileEntry} file The underlying FileEntry object.355* @constructor356* @extends {goog.fs.EntryImpl}357* @implements {goog.fs.FileEntry}358* @final359*/360goog.fs.FileEntryImpl = function(fs, file) {361goog.fs.FileEntryImpl.base(this, 'constructor', fs, file);362363/**364* The underlying FileEntry object.365*366* @type {!FileEntry}367* @private368*/369this.file_ = file;370};371goog.inherits(goog.fs.FileEntryImpl, goog.fs.EntryImpl);372373374/** @override */375goog.fs.FileEntryImpl.prototype.createWriter = function() {376var d = new goog.async.Deferred();377this.file_.createWriter(function(w) {378d.callback(new goog.fs.FileWriter(w));379}, goog.bind(function(err) {380var msg = 'creating writer for ' + this.getFullPath();381d.errback(new goog.fs.Error(err, msg));382}, this));383return d;384};385386387/** @override */388goog.fs.FileEntryImpl.prototype.file = function() {389var d = new goog.async.Deferred();390this.file_.file(function(f) { d.callback(f); }, goog.bind(function(err) {391var msg = 'getting file for ' + this.getFullPath();392d.errback(new goog.fs.Error(err, msg));393}, this));394return d;395};396397398