00001
00002
00003 #include "orbsvcs/Notify/XML_Saver.h"
00004
00005 #include "ACEXML/common/XML_Util.h"
00006
00007 #include "ace/High_Res_Timer.h"
00008 #include "ace/OS_NS_stdio.h"
00009 #include "ace/OS_NS_unistd.h"
00010
00011 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00012
00013 namespace TAO_Notify
00014 {
00015 extern const char TOPOLOGY_ID_NAME[];
00016
00017 XML_Saver::XML_Saver(bool timestamp)
00018 : output_ (0)
00019 , close_out_ (false)
00020 , backup_count_ (1)
00021 , timestamp_ (timestamp)
00022 {
00023 }
00024
00025 XML_Saver::~XML_Saver()
00026 {
00027 if (this->output_ != 0)
00028 {
00029 ACE_ERROR ((LM_ERROR,
00030 ACE_TEXT ("(%P|%t) XML_Saver warning close not called or failed\n")
00031 ));
00032 }
00033 }
00034
00035 void
00036 XML_Saver::backup_file_name (ACE_TCHAR * file_path, size_t nfile)
00037 {
00038 ACE_OS::snprintf(file_path, MAXPATHLEN, ACE_TEXT("%s.%3.3d"),
00039 this->base_name_.c_str (),
00040 nfile);
00041 }
00042
00043 void
00044 XML_Saver::close (void)
00045 {
00046 if (this->close_out_ && this->output_ != 0)
00047 {
00048 this->end_object(0, "notification_service");
00049
00050 ACE_OS::fclose(this->output_);
00051 this->output_ = 0;
00052
00053
00054 size_t nfile = this->backup_count_ - 1;
00055 ACE_TCHAR old_path [MAXPATHLEN + 1];
00056 backup_file_name (old_path, nfile);
00057 ACE_OS::unlink (old_path);
00058
00059 while (nfile != 0)
00060 {
00061 ACE_TCHAR new_path [MAXPATHLEN + 1];
00062 nfile -= 1;
00063 backup_file_name (new_path, nfile);
00064
00065 ACE_OS::rename (new_path, old_path);
00066 ACE_OS::strcpy (old_path, new_path);
00067 }
00068
00069 ACE_TString xml_name = this->base_name_;
00070 xml_name += ACE_TEXT(".xml");
00071
00072 ACE_OS::rename (xml_name.c_str (), old_path);
00073
00074 ACE_TString new_name = this->base_name_;
00075 new_name += ACE_TEXT(".new");
00076 ACE_OS::rename (new_name.c_str (), xml_name.c_str ());
00077 }
00078 this->output_ = 0;
00079 }
00080
00081 bool
00082 XML_Saver::open(const ACE_TString & base_name, size_t backup_count)
00083 {
00084 this->base_name_ = base_name;
00085 this->backup_count_ = backup_count;
00086 if (base_name == ACE_TEXT("cout"))
00087 {
00088 this->output_ = stdout;
00089 this->close_out_ = false;
00090 }
00091 else if (base_name == ACE_TEXT("cerr"))
00092 {
00093 this->output_ = stderr;
00094 this->close_out_ = false;
00095 }
00096 else
00097 {
00098 ACE_TString file_name = base_name;
00099 file_name += ACE_TEXT(".new");
00100
00101 this->output_ = ACE_OS::fopen (file_name.c_str(), ACE_TEXT("wb"));
00102 if (this->output_) {
00103 this->close_out_ = true;
00104 } else {
00105 ACE_ERROR ((LM_ERROR,
00106 ACE_TEXT ("(%P|%t) XML_Saver unable to open %s\n"),
00107 base_name.c_str()));
00108 }
00109 }
00110 if (this->output_ != 0)
00111 {
00112 FILE * const out = this->output_;
00113
00114 ACE_OS::fprintf (out, "<?xml version=\"1.0\"?>\n");
00115
00116 try
00117 {
00118 bool changed = true;
00119 NVPList attrs;
00120
00121 ACE_Time_Value const now = ACE_High_Res_Timer::gettimeofday();
00122
00123 ACE_UINT64 nowus = now.usec();
00124 static const ACE_UINT64 USECSPERSEC = 1000 * 1000;
00125 ACE_UINT64 const tmpus = now.sec();
00126 nowus += tmpus * USECSPERSEC;
00127
00128 ACE_TCHAR nowusstr[128];
00129 #ifdef ACE_LACKS_LONGLONG_T
00130 nowus.as_string(nowusstr);
00131 #else
00132 ACE_OS::sprintf(nowusstr, ACE_UINT64_FORMAT_SPECIFIER, nowus);
00133 #endif
00134
00135 attrs.push_back(NVP("version", "1.0"));
00136 if (this->timestamp_)
00137 {
00138 attrs.push_back(NVP("timestamp", ACE_TEXT_ALWAYS_CHAR(nowusstr)));
00139 }
00140 this->begin_object(0, "notification_service", attrs, changed);
00141 }
00142 catch (const CORBA::Exception& ex)
00143 {
00144 ex._tao_print_exception (
00145 ACE_TEXT (
00146 "(%P|%t) XML_Saver Unknown exception\n"));
00147 if (this->close_out_ && this->output_ != 0)
00148 {
00149 (void) ACE_OS::fclose (this->output_);
00150 }
00151
00152 this->output_ = 0;
00153 }
00154 }
00155 return this->output_ != 0;
00156 }
00157
00158 bool
00159 XML_Saver::begin_object(CORBA::Long id,
00160 const ACE_CString& type,
00161 const NVPList& attrs,
00162 bool )
00163 {
00164 ACE_ASSERT(this->output_ != 0);
00165
00166 FILE * const out = this->output_;
00167
00168 ACE_OS::fprintf (out, "%s%s%s", indent_.c_str(), "<", type.c_str());
00169 if (id != 0)
00170 {
00171
00172 long const lid = id;
00173 ACE_OS::fprintf (out, " %s%s%ld%s", TOPOLOGY_ID_NAME, "=\"", lid, "\"");
00174 }
00175
00176 ACE_TString::size_type const BUF_SIZE = 512;
00177 ACE_TString tmp(BUF_SIZE);
00178 for (size_t idx = 0; idx < attrs.size(); ++idx)
00179 {
00180 ACE_TString valuetmp (ACE_TEXT_CHAR_TO_TCHAR (attrs[idx].value.c_str()));
00181 ACEXML_escape_string(valuetmp, tmp);
00182 ACE_OS::fprintf (out, "%s%s%s%s%s"," ",
00183 attrs[idx].name.c_str (),
00184 "=\"", ACE_TEXT_ALWAYS_CHAR (tmp.c_str()), "\"");
00185 }
00186 ACE_OS::fprintf (out, ">\n");
00187 this->indent_ += " ";
00188 return true;
00189 }
00190
00191 void XML_Saver::end_object (CORBA::Long ,
00192 const ACE_CString& type)
00193 {
00194 ACE_ASSERT(this->output_ != 0);
00195 FILE * const out = this->output_;
00196 if (this->indent_.length() >= 2)
00197 {
00198 this->indent_ = this->indent_.substr(2);
00199 }
00200 ACE_OS::fprintf (out, "%s%s%s%s", indent_.c_str(), "</",
00201 type.c_str(), ">\n");
00202 }
00203 }
00204
00205 TAO_END_VERSIONED_NAMESPACE_DECL