Statistics
| Branch: | Revision:

root / trunk / Pithos.Interfaces / ObjectInfo.cs @ 6bcdd8e2

History | View | Annotate | Download (11.3 kB)

1
#region
2
/* -----------------------------------------------------------------------
3
 * <copyright file="ObjectInfo.cs" company="GRNet">
4
 * 
5
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or
8
 * without modification, are permitted provided that the following
9
 * conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above
12
 *      copyright notice, this list of conditions and the following
13
 *      disclaimer.
14
 *
15
 *   2. Redistributions in binary form must reproduce the above
16
 *      copyright notice, this list of conditions and the following
17
 *      disclaimer in the documentation and/or other materials
18
 *      provided with the distribution.
19
 *
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 * The views and conclusions contained in the software and
35
 * documentation are those of the authors and should not be
36
 * interpreted as representing official policies, either expressed
37
 * or implied, of GRNET S.A.
38
 * </copyright>
39
 * -----------------------------------------------------------------------
40
 */
41
#endregion
42
using System;
43
using System.Collections.Generic;
44
using System.Diagnostics;
45
using System.Diagnostics.Contracts;
46
using System.Dynamic;
47
using System.Globalization;
48
using System.IO;
49
using System.Linq;
50
using System.Text;
51
using Newtonsoft.Json;
52

    
53
namespace Pithos.Interfaces
54
{
55
    [DebuggerDisplay("Name {Name}")]
56
    public class ObjectInfo//:DynamicObject 
57
    {
58
        private readonly List<string> _knownContainers= new List<string>{"trash"};
59
        public string Name { get; set; }
60
        
61
        
62
        public string Hash { get; set; }
63

    
64
        public string X_Object_Hash { get { return Hash; } set { Hash = value; } }
65

    
66
        [JsonProperty("x_object_uuid")]
67
        public string UUID { get; set; }
68

    
69
        public long Bytes { get; set; }
70
        public string Content_Type { get; set; }
71
        public DateTime Last_Modified { get; set; }
72

    
73
        private Dictionary<string, string> _tags=new Dictionary<string, string>();
74
        public Dictionary<string, string> Tags
75
        {
76
            get { return _tags; }
77
            set { _tags = value; }
78
        }
79

    
80
        private Dictionary<string, string> _extensions=new Dictionary<string, string>();
81
        public Dictionary<string, string> Extensions
82
        {
83
            get { return _extensions; }
84
            set
85
            {
86
                _extensions = value;
87
                ExtractKnownExtensions();
88
            }
89
        }
90
        
91
        
92
        private Dictionary<string, string> _permissions=new Dictionary<string, string>();
93
        [JsonProperty("x_object_sharing")]
94
        [JsonConverter(typeof(PermissionConverter))]
95
        public Dictionary<string, string> Permissions
96
        {
97
            get { return _permissions; }
98
            set
99
            {
100
                _permissions = value;                
101
            }
102
        }
103

    
104
        /// <summary>
105
        /// Version number
106
        /// </summary>
107
        [JsonProperty("x_object_version")]
108
        public long? Version { get; set; }
109

    
110

    
111
        /// <summary>
112
        /// Shared object permissions can be Read or Write
113
        /// </summary>
114
        [JsonProperty("x_object_allowed_to")]
115
        public string AllowedTo { get; set; }
116

    
117

    
118
        /// <summary>
119
        /// Version timestamp
120
        /// </summary>
121
        [JsonProperty("X_Object_Version_Timestamp"), JsonConverter(typeof(PithosDateTimeConverter))]
122
        public DateTime? VersionTimestamp { get; set; }
123

    
124
        [JsonProperty("X_Object_Modified_By")]
125
        public string ModifiedBy { get; set; }
126

    
127

    
128
        public Stream Stream { get; set; }
129

    
130

    
131
        public Uri StorageUri { get; set; }
132

    
133
        public string Account { get; set; }
134

    
135
        public string Container { get; set; }
136

    
137
        public Uri Uri
138
        {
139
            get
140
            {
141
                var relativeUrl=String.Format("{0}/{1}/{2}",Account, Container,Name);
142
                return StorageUri==null 
143
                    ? new Uri(relativeUrl,UriKind.Relative) 
144
                    : new Uri(StorageUri, relativeUrl);
145
            }
146
        }
147

    
148
        public string ContendDisposition { get; set; }
149

    
150
        public string ContentEncoding { get; set; }
151

    
152
        public string Manifest { get; set; }
153
        
154
        public bool IsPublic
155
        {
156
            get { return !String.IsNullOrWhiteSpace(PublicUrl); }
157
            set
158
            {
159
                if (!value)
160
                    PublicUrl = null;
161
                else if (String.IsNullOrWhiteSpace(PublicUrl))
162
                    PublicUrl="true";                
163
            }
164
        }
165

    
166
        [JsonProperty("X_Object_Public")]
167
        public string PublicUrl { get; set; }
168

    
169
        public string PreviousHash { get; set; }
170

    
171
        public ObjectInfo()
172
        {}
173

    
174
        public ObjectInfo(string accountPath,string accountName,FileSystemInfo fileInfo)
175
        {
176
            if (String.IsNullOrWhiteSpace(accountPath))
177
                throw new ArgumentNullException("accountPath");
178
            if (string.IsNullOrWhiteSpace(accountName))
179
                throw new ArgumentNullException("accountName");
180
            if (fileInfo == null)
181
                throw new ArgumentNullException("fileInfo");
182
            Contract.EndContractBlock();
183

    
184
            var relativeUrl = fileInfo.WithProperCapitalization().AsRelativeUrlTo(accountPath);
185
            //The first part of the URL is the container
186
            var slashIndex = relativeUrl.IndexOf('/');
187
            var container = relativeUrl.Substring(0, slashIndex);
188
            //The second is the file's url relative to the container
189
            var fileUrl = relativeUrl.Substring(slashIndex + 1);
190

    
191
            Account = accountName;
192
            Container = container;
193
            Name = fileUrl; 
194
        }
195

    
196

    
197
        private void ExtractKnownExtensions()
198
        {
199
            Version=GetLong(KnownExtensions.X_Object_Version);
200
            VersionTimestamp = GetTimestamp(KnownExtensions.X_Object_Version_Timestamp);
201
            ModifiedBy = GetString(KnownExtensions.X_Object_Modified_By);
202
        }
203

    
204
        private string GetString(string name)
205
        {            
206
            string value;
207
            _extensions.TryGetValue(name, out value);
208
            return value ;                        
209
        }
210
        
211
        private long? GetLong(string name)
212
        {
213
            string version;
214
            long value;
215
            return _extensions.TryGetValue(name, out version) && long.TryParse(version, out value)
216
                       ? (long?) value
217
                       : null;
218
        }
219

    
220
        private DateTime? GetTimestamp(string name)
221
        {
222
            string version;
223
            DateTime value;
224
            if (_extensions.TryGetValue(name, out version) && 
225
                DateTime.TryParse(version,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal, out value))
226
            {
227
                return value;
228
            }
229
            return null;
230
        }
231

    
232

    
233
        public static ObjectInfo Empty = new ObjectInfo
234
        {
235
            Name = String.Empty,
236
            Hash = String.Empty,
237
            Bytes = 0,
238
            Content_Type = String.Empty,
239
            Last_Modified = DateTime.MinValue,
240
            Exists=false
241
        };
242

    
243
        private bool _exists=true;
244

    
245
        public bool Exists
246
        {
247
            get {
248
                return _exists;
249
            }
250
            set {
251
                _exists = value;
252
            }
253
        }
254

    
255

    
256
        public string RelativeUrlToFilePath(string currentAccount)
257
        {
258
            if (Name==null)
259
                throw new InvalidOperationException("Name can't be null");
260
            if (String.IsNullOrWhiteSpace(currentAccount))
261
                throw new ArgumentNullException("currentAccount");
262
            Contract.EndContractBlock();
263

    
264
            if (this == Empty)
265
                return String.Empty;
266

    
267
            var unescaped = Uri.UnescapeDataString(Name);
268
            var path = unescaped.Replace("/", "\\");
269
            var pathParts=new Stack<string>();
270
            pathParts.Push(path);
271
            if (!String.IsNullOrWhiteSpace(Container) && !_knownContainers.Contains(Container))
272
                pathParts.Push(Container);
273
            if (!currentAccount.Equals(Account, StringComparison.InvariantCultureIgnoreCase))
274
            {
275
                if (Account != null)
276
                {
277
                    pathParts.Push(Account);
278
                    pathParts.Push(FolderConstants.OthersFolder);
279
                }
280
            }
281
            var finalPath=Path.Combine(pathParts.ToArray());
282
            return finalPath;
283
        }
284

    
285
/*
286
        public override bool TrySetMember(SetMemberBinder binder, object value)
287
        {
288
            if (binder.Name.StartsWith("x_object_meta"))
289
            {
290
                Tags[binder.Name] = value.ToString();
291
            }
292
            return false;
293
        }
294
*/
295

    
296
        public string GetPermissionString()
297
        {
298
            if (Permissions==null)
299
                throw new InvalidOperationException();
300
            Contract.EndContractBlock();
301

    
302
            var permissionBuilder = new StringBuilder();
303
            var groupings = Permissions.GroupBy(pair => pair.Value, pair => pair.Key);
304
            foreach (var grouping in groupings)
305
            {
306
                permissionBuilder.AppendFormat("{0}={1};", grouping.Key, String.Join(",", grouping));
307
            }
308
            var permissions = permissionBuilder.ToString().Trim(';');
309
            return permissions;
310
        }
311

    
312
        public void SetPermissions(string permissions)
313
        {
314
            if (String.IsNullOrWhiteSpace(permissions))
315
                return;
316

    
317
            var permDict=new Dictionary<string, string>();
318
            var perms=permissions.Split(';');
319
            foreach (var perm in perms)
320
            {
321
                var permPairs=perm.Split('=');
322
                var right = permPairs[0];
323
                var users= permPairs[1].Split(new[]{','},StringSplitOptions.RemoveEmptyEntries);
324
                foreach (var user in users)
325
                {
326
                    permDict[user] = right;
327
                }
328
            }
329
            Permissions = permDict;
330
        }
331

    
332
        //The previous values that correspond to a NoModification object
333
        //have the same account, container and possibly the same folder
334
        public bool CorrespondsTo(ObjectInfo other)
335
        {
336
            return other.Account == this.Account
337
                   && other.Container == this.Container
338
                   && (this.Name == null || other.Name.StartsWith(this.Name));
339
        }
340

    
341

    
342
        public ObjectInfo Previous { get; private set; }
343

    
344
        public ObjectInfo SetPrevious(ObjectInfo previous)
345
        {            
346
            Previous = previous;
347
            PreviousHash = previous.Hash;
348
            return this;
349
        }
350
    }
351
}