1 /**
  2  * @fileOverview Base Connection.
  3  */
  4 
  5 (function () {
  6   var utils = require("../utils"),
  7     CloudError = require("../errors").CloudError,
  8     Connection;
  9 
 10   /**
 11    * Abstract base connection class.
 12    *
 13    * @param {base.Authentication} auth Authentication object.
 14    * @exports Connection as base.Connection
 15    * @constructor
 16    */
 17   Connection = function (auth) {
 18     var self = this;
 19 
 20     // Validation.
 21     if (!auth) { throw new Error("No authentication object."); }
 22 
 23     self._auth = auth;
 24 
 25     // Header prefixes.
 26     self._HEADER_PREFIX = null;
 27     self._METADATA_PREFIX = null;
 28 
 29     // Map errors to class.
 30     self._ERRORS = {
 31       CONTAINER_NOT_FOUND: {
 32         attrs: null,
 33         error: {
 34           message: "Container not found.",
 35           types: CloudError.TYPES.NOT_FOUND
 36         },
 37         errorMap: null
 38       },
 39       CONTAINER_NOT_EMPTY: {
 40         attrs: null,
 41         error: {
 42           message: "Container not empty.",
 43           types: CloudError.TYPES.NOT_EMPTY
 44         },
 45         errorMap: null
 46       },
 47       CONTAINER_INVALID_NAME: {
 48         attrs: null,
 49         error: {
 50           message: "Invalid container name.",
 51           types: CloudError.TYPES.INVALID_NAME
 52         },
 53         errorMap: null
 54       },
 55       CONTAINER_OTHER_OWNER: {
 56         attrs: null,
 57         error: {
 58           message: "Container already owned by another.",
 59           types: CloudError.TYPES.NOT_OWNER
 60         },
 61         errorMap: null
 62       },
 63       // **Note**: This is mapped to non-error for GSFD and not used elsewhere.
 64       CONTAINER_ALREADY_OWNED_BY_YOU: {
 65         attrs: null,
 66         error: {
 67           message: "Container already owned by you.",
 68           types: CloudError.TYPES.ALREADY_OWNED_BY_YOU
 69         },
 70         errorMap: null
 71       },
 72       BLOB_NOT_FOUND: {
 73         attrs: null,
 74         error: {
 75           message: "Blob not found.",
 76           types: CloudError.TYPES.NOT_FOUND
 77         },
 78         errorMap: null
 79       },
 80       BLOB_INVALID_NAME: {
 81         attrs: null,
 82         error: {
 83           message: "Invalid blob name.",
 84           types: CloudError.TYPES.INVALID_NAME
 85         },
 86         errorMap: null
 87       }
 88     };
 89   };
 90 
 91   Object.defineProperties(Connection.prototype, {
 92     /**
 93      * Cloud header prefix (e.g., 'x-amz-').
 94      *
 95      * @name Connection#headerPrefix
 96      * @type string
 97      */
 98     headerPrefix: {
 99       get: function () {
100         return this._HEADER_PREFIX;
101       }
102     },
103 
104     /**
105      * Cloud header metadata prefix (e.g., 'x-amz-meta-').
106      *
107      * @name Connection#metadataPrefix
108      * @type string
109      */
110     metadataPrefix: {
111       get: function () {
112         return this._METADATA_PREFIX;
113       }
114     },
115 
116     /**
117      * Authentication object.
118      *
119      * @name Connection#authentication
120      * @type base.Authentication
121      */
122     authentication: {
123       get: function () {
124         return this._auth;
125       }
126     }
127   });
128 
129   /**
130    * Create container object.
131    * @private
132    */
133   Connection.prototype._createContainer = function (name) {
134     throw new Error("Not implemented.");
135   };
136 
137   /**
138    * Check if known error.
139    *
140    * @returns {boolean} True if error.
141    * @private
142    */
143   Connection.prototype._isError = function (errItem, err, response) {
144     throw new Error("Not implemented.");
145   };
146 
147   /**
148    * Translate errors.
149    *
150    * @returns {Error|errors.CloudError} Translated error.
151    * @private
152    */
153   Connection.prototype._translateErrors = function (err, request, response) {
154     var self = this,
155       key,
156       errObj,
157       error;
158 
159     for (key in self._ERRORS) {
160       if (self._ERRORS.hasOwnProperty(key)) {
161         errObj = self._ERRORS[key];
162         if (self._isError(errObj, err, response)) {
163           // Favor errorMap over default error.
164           error = errObj.errorMap
165             ? (errObj.errorMap[request.method] || errObj.error)
166             : errObj.error;
167 
168           if (!error) {
169             throw new Error("Undefined error for errObj: " + errObj +
170                             ", err: " + err);
171           }
172 
173           return new CloudError(error.message, {
174             error: err,
175             types: error.types,
176             response: response
177           });
178         }
179       }
180     }
181 
182     return null;
183   };
184 
185   /**
186    * Completion event ('``end``').
187    *
188    * @name base.Connection#getContainers_end
189    * @event
190    * @param   {Object}  results     Results object.
191    * @config  {Array}   containers  List of container objects.
192    */
193   /**
194    * Error event ('``error``').
195    *
196    * @name base.Connection#getContainers_error
197    * @event
198    * @param   {Error|errors.CloudError} err Error object.
199    */
200   /**
201    * Get a list of Containers.
202    *
203    * ## Events
204    *  - [``end(results, meta)``](#getContainers_end)
205    *  - [``error(err)``](#getContainers_error)
206    *
207    * ## Note
208    * Both AWS and GSFD only offer listing **all** containers, without
209    * paging or prefix options.
210    *
211    * @param   {Object}  [options]         Options object.
212    * @config  {Object}  [headers]         Raw headers to add.
213    * @config  {Object}  [cloudHeaders]    Cloud provider headers to add.
214    * @config  {Object}  [metadata]        Cloud metadata to add.
215    * @returns {AuthenticatedRequest} Request object.
216    */
217   Connection.prototype.getContainers = function (options) {
218     throw new Error("Not implemented.");
219   };
220 
221   /**
222    * Create container object and GET.
223    *
224    * @see base.blob.Container#get
225    */
226   Connection.prototype.getContainer = function (name, options) {
227     return this._createContainer(name).get(options);
228   };
229 
230   /**
231    * Create container object and PUT.
232    *
233    * @see base.blob.Container#put
234    */
235   Connection.prototype.putContainer = function (name, options) {
236     return this._createContainer(name).put(options);
237   };
238 
239   /**
240    * Create container object and DELETE.
241    *
242    * @see base.blob.Container#del
243    */
244   Connection.prototype.delContainer = function (name, options) {
245     return this._createContainer(name).del(options);
246   };
247 
248   module.exports.Connection = Connection;
249 }());
250