libs/EDoc/Persistence.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003    Copyright (C) 2007 by Brendon Costa
00004 
00005    This library is free software; you can redistribute it and/or modify 
00006    it under the terms of the "LGPL Like" License defined in the file COPYING 
00007    that should have been distributed along with this source.
00008 
00009    This library is distributed in the hope that it will be useful, 
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of 
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013    You should have received a copy of the "LGPL Like" License 
00014    along with this library; see the file COPYING. if not, it can be 
00015    obtained from the EDoc++ website: 
00016    http://edoc.sourceforge.net/license.html
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 // EDoc Namespace Implementation.
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       // Try to open file in one of the archive formats.
00094       EDOC_FOREACH(ArchiveList, arch, archive_formats)
00095       {
00096          if ((*arch)->HandlesType(filename))
00097          {
00098             // List all files in archive.
00099             // Open each file in list
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       // Otherwise if we get here then we will just add the given file as a
00112       // source.
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       // Get all possible files by extracting known archives.
00123       std::list<ManagedFile> poss_files(ReadExtract(ManagedFile(filename)));
00124       
00125       // For each file in list, check to see if it is a valid edoc file. If not
00126       // then discard it.
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             // If we catch this then skip that file.
00138             EDOC_Debug("Invalid edoc file: " << pf->GetName() 
00139                << ", Reason: " << e.what());
00140          }
00141       }
00142       
00143       // Return a list of all valid edc file found.
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       // First see if the file given is a valid archive name.
00153       EDOC_FOREACH(ArchiveList, arch, archive_formats)
00154       {
00155          if ((*arch)->HandlesType(f))
00156          {
00157             // If it is an archive then prepare a file from it for writing.
00158             ManagedFile f2 = (*arch)->WriteOpen(f, item_name);
00159             return Persistence(false, f2, format);
00160          }
00161       }
00162       
00163       // Otherwise we will assume that the file is to be written directly as an
00164       // edc file.
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          // Read the 1st 9 characters
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 }

Generated on Tue Jan 20 18:26:07 2009 for EDoc-0.2.1 by  doxygen 1.5.1