00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020
00021 #include "EDoc/Persistence.h"
00022 #include "EDoc/exceptions.h"
00023 #include "EDoc/TextPersistence.h"
00024 #include "EDoc/BinaryPersistence.h"
00025 #include "EDoc/stdint.h"
00026 #include "EDoc/utils.h"
00027 #include "EDoc/persistence_data.h"
00028 #include "EDoc/ArchiveIFace.h"
00029
00030
00031 #include <iostream>
00032 #include <algorithm>
00033
00034 #ifdef HAVE_STRING_H
00035 #include <string.h>
00036 #endif
00037
00038 #ifdef HAVE_FCNTL_H
00039 #include <fcntl.h>
00040 #endif
00041
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045
00046 #ifdef HAVE_ERRNO_H
00047 #include <errno.h>
00048 #endif
00049
00050
00051
00052
00053
00054 namespace EDoc
00055 {
00056
00057 std::list<std::string> Persistence::temp_files;
00058 std::list<ArchiveIFace*> Persistence::archive_formats;
00059
00060 void Persistence::AddTempFile(std::string filename)
00061 {
00062 if (std::find(temp_files.begin(), temp_files.end(), filename) !=
00063 temp_files.end())
00064 {
00065 EDOC_Warning("File already in temp file list: " << filename);
00066 return;
00067 }
00068
00069 temp_files.push_back(filename);
00070 }
00071
00072 void Persistence::RemoveTempFile(std::string filename)
00073 {
00074 std::list<std::string>::iterator it = std::find(temp_files.begin(),
00075 temp_files.end(), filename);
00076 if (it == temp_files.end())
00077 {
00078 EDOC_Warning("Temp file does not exist to be erased: " << filename);
00079 return;
00080 }
00081 temp_files.erase(it);
00082 }
00083
00084 void Persistence::AddArchiveFactory(ArchiveIFace* factory)
00085 {
00086 archive_formats.push_back(factory);
00087 }
00088
00089 std::list<ManagedFile> Persistence::ReadExtract(ManagedFile filename)
00090 {
00091 std::list<ManagedFile> files;
00092
00093
00094 EDOC_FOREACH(ArchiveList, arch, archive_formats)
00095 {
00096 if ((*arch)->HandlesType(filename))
00097 {
00098
00099
00100 std::list<ManagedFile> poss_files = (*arch)->ReadExtractAll(filename);
00101 EDOC_FOREACH(MngdFileList, pf, poss_files)
00102 {
00103 Append(files, ReadExtract(*pf));
00104 }
00105
00106 EDOC_Fine("Pushing archives set of managed files. Count: " << files.size());
00107 return files;
00108 }
00109 }
00110
00111
00112
00113 EDOC_Fine("Pushing non-archive managed file: " << filename.GetName());
00114 files.push_back(filename);
00115 return files;
00116 }
00117
00118 std::list<Persistence> Persistence::ReadOpen(std::string filename)
00119 {
00120 std::list<Persistence> ret;
00121
00122
00123 std::list<ManagedFile> poss_files(ReadExtract(ManagedFile(filename)));
00124
00125
00126
00127 EDOC_FOREACH(MngdFileList, pf, poss_files)
00128 {
00129 try
00130 {
00131 Persistence p(true, *pf, UNKNOWN);
00132 ret.push_back(p);
00133 EDOC_Fine("Got valid edoc file: " << pf->GetName());
00134 }
00135 catch(UnknownFileTypeException& e)
00136 {
00137
00138 EDOC_Debug("Invalid edoc file: " << pf->GetName()
00139 << ", Reason: " << e.what());
00140 }
00141 }
00142
00143
00144 return ret;
00145 }
00146
00147 Persistence Persistence::WriteOpen(std::string filename,
00148 EncodingType format, std::string item_name)
00149 {
00150 ManagedFile f(filename);
00151
00152
00153 EDOC_FOREACH(ArchiveList, arch, archive_formats)
00154 {
00155 if ((*arch)->HandlesType(f))
00156 {
00157
00158 ManagedFile f2 = (*arch)->WriteOpen(f, item_name);
00159 return Persistence(false, f2, format);
00160 }
00161 }
00162
00163
00164
00165 return Persistence(false, f, format);
00166 }
00167
00168 Persistence::Persistence(const Persistence& right) :
00169 EDoc::PersistenceIFace(),
00170
00171 file(right.file),
00172 format(right.format),
00173 impl(right.impl)
00174 {
00175 IncRef();
00176 }
00177
00178 Persistence::Persistence(bool read,
00179 ManagedFile file_in,
00180 EncodingType format_in) :
00181 EDoc::PersistenceIFace(),
00182
00183 file(file_in),
00184 format(format_in),
00185 impl(NULL)
00186 {
00187 if (read)
00188 {
00189 EDOC_ASSERT(format == UNKNOWN, "");
00190
00191 std::ifstream f(file.GetWorkFileName().c_str(), std::ios::binary);
00192 if (!f)
00193 {
00194 EDOC_THROW_EXCEPTION(FileIOException,
00195 strerror(errno),
00196 "filename: " << file.GetWorkFileName());
00197 }
00198
00199 char temp[10];
00200
00201
00202 f.read(temp, 9);
00203 if (!f)
00204 {
00205 EDOC_THROW_EXCEPTION(UnknownFileTypeException,
00206 "Failed reading file header.",
00207 "filename: " << file.GetWorkFileName()
00208 << ", reason: " << strerror(errno));
00209 }
00210
00211 temp[9] = 0;
00212 if (!strcmp(temp, "EDoc: TXT"))
00213 {
00214 impl = new TextPersistence(read, file.GetWorkFileName());
00215 IncRef();
00216 format = TEXT;
00217 }
00218 else if (!strcmp(temp, "EDoc: BIN"))
00219 {
00220 impl = new BinaryPersistence(read, file.GetWorkFileName());
00221 IncRef();
00222 format = BINARY;
00223 }
00224 else
00225 {
00226 EDOC_THROW_EXCEPTION(UnknownFileTypeException,
00227 "Unknown file format.", "");
00228 }
00229 }
00230 else
00231 {
00232 switch (format)
00233 {
00234 case TEXT:
00235 {
00236 impl = new TextPersistence(read, file.GetWorkFileName());
00237 IncRef();
00238 break;
00239 }
00240 case BINARY:
00241 {
00242 impl = new BinaryPersistence(read, file.GetWorkFileName());
00243 IncRef();
00244 break;
00245 }
00246 default:
00247 {
00248 EDOC_ASSERT(false, "Unknown format inputfor writing.");
00249 }
00250 }
00251 }
00252
00253 EDOC_ASSERT(impl, "");
00254 }
00255
00256 Persistence& Persistence::operator=(const Persistence& right)
00257 {
00258 if (this == &right)
00259 {
00260 return *this;
00261 }
00262
00263 DecRef();
00264
00265 file = right.file;
00266 format = right.format;
00267 impl = right.impl;
00268
00269 IncRef();
00270
00271 return *this;
00272 }
00273
00274 Persistence::~Persistence()
00275 {
00276 DecRef();
00277 }
00278
00279 void Persistence::IncRef()
00280 {
00281 if (impl)
00282 {
00283 impl->ref_count++;
00284 }
00285 }
00286
00287 void Persistence::DecRef()
00288 {
00289 if (impl)
00290 {
00291 impl->ref_count--;
00292 if (impl->ref_count <= 0)
00293 {
00294 delete impl;
00295 impl = NULL;
00296 }
00297 }
00298 }
00299
00300 std::string Persistence::GetFilenameRep() const
00301 {
00302 return file.GetFileNameRep();
00303 }
00304
00305 }