1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using ICSharpCode.SharpZipLib.Zip;
namespace Monodoc.Storage
{
public class ZipStorage : IDocStorage
{
string zipFileName;
int code;
ZipOutputStream zipOutput;
ZipFile zipFile;
// SharpZipLib use linear search to map name to index, correct that a bit
Dictionary<string, int> entries = new Dictionary<string, int> ();
public ZipStorage (string zipFileName)
{
this.zipFileName = zipFileName;
}
public bool SupportRevision {
get {
return false;
}
}
public IDocRevisionManager RevisionManager {
get {
return null;
}
}
public bool SupportChange {
get {
return true;
}
}
public string Store (string id, string text)
{
EnsureOutput ();
SetupEntry (zipOutput, ref id);
var writer = new StreamWriter (zipOutput);
writer.Write (text);
writer.Flush ();
return id;
}
public string Store (string id, byte[] data)
{
EnsureOutput ();
SetupEntry (zipOutput, ref id);
zipOutput.Write (data, 0, data.Length);
return id;
}
public string Store (string id, Stream stream)
{
EnsureOutput ();
SetupEntry (zipOutput, ref id);
stream.CopyTo (zipOutput);
return id;
}
void SetupEntry (ZipOutputStream zipOutput, ref string id)
{
if (string.IsNullOrEmpty (id))
id = GetNewCode ();
ZipEntry entry = new ZipEntry (id);
zipOutput.PutNextEntry (entry);
}
public Stream Retrieve (string id)
{
EnsureInput ();
int index;
ZipEntry entry;
if (!entries.TryGetValue (id, out index) || (entry = zipFile[index]) == null)
entry = zipFile.GetEntry (id);
if (entry != null)
return zipFile.GetInputStream (entry);
else
throw new ArgumentException ("id", string.Format ("'{0}' isn't a valid id for this storage", id));
}
public IEnumerable<string> GetAvailableIds ()
{
EnsureInput ();
return zipFile.Cast<ZipEntry> ().Select (ze => ze.Name);
}
void EnsureOutput ()
{
if (zipFile != null)
throw new InvalidOperationException ("This ZipStorage instance is already used in read-mode");
if (zipOutput != null)
return;
zipOutput = new ZipOutputStream (File.Create (zipFileName));
#if !MONO
zipOutput.UseZip64 = UseZip64.Off;
#endif
}
void EnsureInput ()
{
if (zipOutput != null)
throw new InvalidOperationException ("This ZipStorage instance is already used in write-mode");
if (zipFile != null)
return;
zipFile = new ZipFile (zipFileName);
entries = Enumerable.Range (0, zipFile.Size).ToDictionary (i => zipFile[i].Name, i => i);
}
public void Dispose ()
{
if (zipOutput != null)
zipOutput.Dispose ();
if (zipFile != null)
zipFile.Close ();
}
string GetNewCode ()
{
return String.Format ("{0}", code++);
}
}
}
|