--- parser3/src/include/pa_stylesheet_connection.h 2001/09/15 11:48:41 1.2 +++ parser3/src/include/pa_stylesheet_connection.h 2003/11/20 16:34:25 1.35 @@ -1,23 +1,22 @@ /** @file - Parser: stylesheet fstylesheet decl. + Parser: Stylesheet connection decl. - Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - - Author: Alexander Petrosyan (http://design.ru/paf) - - $Id: pa_stylesheet_connection.h,v 1.2 2001/09/15 11:48:41 parser Exp $ + Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ #ifndef PA_STYLESHEET_CONNECTION_H #define PA_STYLESHEET_CONNECTION_H -#include "pa_config_includes.h" -#include "pa_pool.h" -#include "pa_xslt_stylesheet_manager.h" -#include "pa_exception.h" -#include "pa_common.h" +static const char * const IDENT_STYLESHEET_CONNECTION_H="$Date: 2003/11/20 16:34:25 $"; -#include +#include "libxslt/xslt.h" +#include "libxslt/xsltInternals.h" + + +#include "pa_xml_exception.h" +#include "pa_common.h" +#include "pa_globals.h" // defines @@ -26,93 +25,136 @@ /** Connection with stylesheet: remembers time and can figure out that it needs recompilation */ -class Stylesheet_connection : public Pooled { +class Stylesheet_connection: public PA_Object { -public: + friend class Stylesheet_connection_ptr; + +private: - Stylesheet_connection(Pool& pool, const String& afile_spec) : Pooled(pool), - ftransformer(new XalanTransformer), + const String& ffile_spec; + xsltStylesheet *fstylesheet; + time_t time_used; + time_t prev_disk_time; + +public: + Stylesheet_connection(const String& afile_spec): ffile_spec(afile_spec), - time_used(0), prev_disk_time(0), - fservices_pool(0) { - } + fstylesheet(0), + time_used(0), used(0) {} const String& file_spec() { return ffile_spec; } - void set_services(Pool *aservices_pool) { - time_used=time(0); // they started to use at this time - fservices_pool=aservices_pool; - } bool expired(time_t older_dies) { - return time_usedclose_connection(ffile_spec, *this); + return !used && time_useddestroyStylesheet(fstylesheet); fstylesheet=0; - - // connection effectively useless now, free up some memory - delete ftransformer; + xsltFreeStylesheet(fstylesheet); fstylesheet=0; } bool connected() { return fstylesheet!=0; } - XalanCompiledStylesheet& stylesheet() { - if(time_t new_disk_time=get_new_disk_time()) + xsltStylesheet *stylesheet(bool nocache) { + time_t new_disk_time=get_new_disk_time(); + if(nocache || new_disk_time) load(new_disk_time); - return *fstylesheet; + return fstylesheet; } private: + /// return to cache + void close(); + +private: + time_t get_new_disk_time() { time_t now_disk_time=get_disk_time(); return now_disk_time>prev_disk_time?now_disk_time:0; } void load(time_t new_disk_time) { - Pool& pool=*fservices_pool; - - int error=ftransformer->compileStylesheet(ffile_spec.cstr(String::UL_FILE_SPEC), fstylesheet); - if(error) - PTHROW(0, 0, + int saved=xmlDoValidityCheckingDefaultValue;// + xmlDoValidityCheckingDefaultValue=0;// + xsltStylesheet *nstylesheet= + xsltParseStylesheetFile(BAD_CAST ffile_spec.cstr(String::L_FILE_SPEC)); + xmlDoValidityCheckingDefaultValue = saved;// + if(xmlHaveGenericErrors()) { + GdomeException exc=0; + throw XmlException(&ffile_spec, exc); + } + if(!nstylesheet) + throw Exception("file.missing", &ffile_spec, - ftransformer->getLastError()); + "stylesheet failed to load"); + xsltFreeStylesheet(fstylesheet); + fstylesheet=nstylesheet; prev_disk_time=new_disk_time; } time_t get_disk_time() { size_t size; time_t atime, mtime, ctime; - String stamp_file_spec(ffile_spec); + String stamp_file_spec(ffile_spec); stamp_file_spec << STYLESHEET_FILENAME_STAMP_SUFFIX; - // {file_spec}.stamp modification time OR {file_spec} mtime - if(!file_stat(file_readable(stamp_file_spec)?stamp_file_spec:ffile_spec, + // {file_spec}.stamp modification time OR {file_spec} + const String& stat_file_spec=file_readable(stamp_file_spec)?stamp_file_spec:ffile_spec; + file_stat(stat_file_spec, size, atime, mtime, ctime, - false/*no exceptions on global pool, please*/)) - mtime=0; // no file=no time + true/*exception on error*/); return mtime; } -private: +private: // connection usage methods - const String& ffile_spec; - XalanCompiledStylesheet *fstylesheet; - time_t time_used; - time_t prev_disk_time; + int used; + void use() { + time_used=time(0); // they started to use at this time + used++; + } + void unuse() { + used--; + if(!used) + close(); + } -private: +}; - XalanTransformer *ftransformer; +/// Auto-object used to track Stylesheet_connection usage +class Stylesheet_connection_ptr { + Stylesheet_connection *fconnection; +public: + explicit Stylesheet_connection_ptr(Stylesheet_connection *aconnection) : + fconnection(aconnection) { + fconnection->use(); + } + ~Stylesheet_connection_ptr() { + fconnection->unuse(); + } + Stylesheet_connection* operator->() { + return fconnection; + } +/* Stylesheet_connection& operator*() { + return *fconnection; + }*/ + + // copying + Stylesheet_connection_ptr(const Stylesheet_connection_ptr& src) : fconnection(src.fconnection) { + fconnection->use(); + } + Stylesheet_connection_ptr& operator =(const Stylesheet_connection_ptr& src) { + // may do without this=src check + fconnection->unuse(); + fconnection=src.fconnection; + fconnection->use(); - Pool *fservices_pool; + return *this; + } }; #endif